2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Asterisk  - -  An  open  source  telephony  toolkit . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Copyright  ( C )  2007  -  2009 ,  Digium ,  Inc . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Joshua  Colp  < jcolp @ digium . com > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  See  http : //www.asterisk.org for more information about
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  Asterisk  project .  Please  do  not  directly  contact 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  any  of  the  maintainers  of  this  project  for  assistance ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  project  provides  a  web  site ,  mailing  lists  and  IRC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  channels  for  your  use . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  program  is  free  software ,  distributed  under  the  terms  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  GNU  General  Public  License  Version  2.  See  the  LICENSE  file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  at  the  top  of  the  source  tree . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \file
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Bridging  API 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ author  Joshua  Colp  < jcolp @ digium . com > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-06-15 16:20:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*** MODULEINFO
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< support_level > core < / support_level > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*** DOCUMENTATION
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< manager  name = " BridgeTechnologyList "  language = " en_US " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-02 14:38:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< version > 12.0 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											List  available  bridging  technologies  and  their  statuses . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< xi : include  xpointer = " xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID']) "  / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< para > Returns  detailed  information  about  the  available  bridging  technologies . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / description > 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-13 20:15:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< see - also > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< ref  type = " manager " > BridgeTechnologySuspend < / ref > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< ref  type = " manager " > BridgeTechnologyUnsuspend < / ref > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / see - also > 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									< / manager > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< manager  name = " BridgeTechnologySuspend "  language = " en_US " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-02 14:38:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< version > 12.0 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Suspend  a  bridging  technology . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< xi : include  xpointer = " xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID']) "  / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< parameter  name = " BridgeTechnology "  required = " true " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > The  name  of  the  bridging  technology  to  suspend . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< para > Marks  a  bridging  technology  as  suspended ,  which  prevents  subsequently  created  bridges  from  using  it . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / description > 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-13 20:15:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< see - also > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< ref  type = " manager " > BridgeTechnologySuspend < / ref > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< ref  type = " manager " > BridgeTechnologyUnsuspend < / ref > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / see - also > 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									< / manager > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< manager  name = " BridgeTechnologyUnsuspend "  language = " en_US " > 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-02 14:38:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< since > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< version > 12.0 .0 < / version > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / since > 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Unsuspend  a  bridging  technology . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< xi : include  xpointer = " xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID']) "  / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< parameter  name = " BridgeTechnology "  required = " true " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< para > The  name  of  the  bridging  technology  to  unsuspend . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / parameter > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / syntax > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< para > Clears  a  previously  suspended  bridging  technology ,  which  allows  subsequently  created  bridges  to  use  it . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / description > 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-13 20:15:58 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										< see - also > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< ref  type = " manager " > BridgeTechnologyList < / ref > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< ref  type = " manager " > BridgeTechnologySuspend < / ref > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / see - also > 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									< / manager > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								* * */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  "asterisk.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/logger.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/channel.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/options.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/utils.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/lock.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/linkedlists.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-07-25 04:06:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/bridge.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/bridge_internal.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/bridge_channel_internal.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-08-02 02:32:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/bridge_features.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-07-25 04:06:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/bridge_basic.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/bridge_technology.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/bridge_channel.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/bridge_after.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/stasis_bridges.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/stasis_channels.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-08-01 13:49:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/stasis_cache_pattern.h" 
  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/app.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/file.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/module.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/astobj2.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/pbx.h" 
  
						 
					
						
							
								
									
										
										
										
											2011-12-22 20:44:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/test.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/_private.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/heap.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/say.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/timing.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/stringfields.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/musiconhold.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/features.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/cli.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/parking.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/core_local.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/core_unreal.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/causes.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! All bridges container. */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ao2_container  * bridges ;  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  AST_RWLIST_HEAD_STATIC ( bridge_technologies ,  ast_bridge_technology ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								AST_MUTEX_DEFINE_STATIC ( bridge_init_lock ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 18:52:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  unsigned  int  optimization_id ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/* Initial starting point for the bridge array of channels */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BRIDGE_ARRAY_START 128 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Grow rate of bridge array of channels */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BRIDGE_ARRAY_GROW 32 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* Variable name - stores peer information about the most recent blind transfer */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BLINDTRANSFER "BLINDTRANSFER" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Variable name - stores peer information about the most recent attended transfer */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define ATTENDEDTRANSFER "ATTENDEDTRANSFER" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  cleanup_video_mode ( struct  ast_bridge  * bridge ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*! Default DTMF keys for built in features */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  builtin_features_dtmf [ AST_BRIDGE_BUILTIN_END ] [ MAXIMUM_DTMF_FEATURE_STRING ] ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! Function handlers for the built in features */  
						 
					
						
							
								
									
										
										
										
											2013-07-24 14:35:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  ast_bridge_hook_callback  builtin_features_handlers [ AST_BRIDGE_BUILTIN_END ] ;  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! Function handlers for built in interval features */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  ast_bridge_builtin_set_limits_fn  builtin_interval_handlers [ AST_BRIDGE_BUILTIN_INTERVAL_END ] ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! Bridge manager service request */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  bridge_manager_request  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! List of bridge service requests. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_ENTRY ( bridge_manager_request )  node ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Refed bridge requesting service. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  bridge_manager_controller  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Condition, used to wake up the bridge manager thread. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_t  cond ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Queue of bridge service requests. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_HEAD_NOLOCK ( ,  bridge_manager_request )  service_requests ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Manager thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pthread_t  thread ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! TRUE if the manager needs to stop. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  stop : 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! Bridge manager controller. */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  bridge_manager_controller  * bridge_manager ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ao2_container  * ast_bridges ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ao2_bump ( bridges ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Request  service  for  a  bridge  from  the  bridge  manager . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  Requesting  service . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_manager_service_req ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_manager_request  * request ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_lock ( bridge_manager ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge_manager - > stop )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlock ( bridge_manager ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Create the service request. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									request  =  ast_calloc ( 1 ,  sizeof ( * request ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! request )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Well. This isn't good. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlock ( bridge_manager ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( bridge ,  + 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									request - > bridge  =  bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Put request into the queue and wake the bridge manager. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_INSERT_TAIL ( & bridge_manager - > service_requests ,  request ,  node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_signal ( & bridge_manager - > cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( bridge_manager ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								int  __ast_bridge_technology_register ( struct  ast_bridge_technology  * technology ,  struct  ast_module  * module )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * current ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Perform a sanity check to make sure the bridge technology conforms to our needed requirements */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( technology - > name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! technology - > capabilities 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! technology - > write )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Bridge technology %s failed registration sanity check. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											technology - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_WRLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Look for duplicate bridge technology already using this name, or already registered */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( & bridge_technologies ,  current ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( ! strcasecmp ( current - > name ,  technology - > name ) )  | |  ( current  = =  technology ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " A bridge technology of %s already claims to exist in our world. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												technology - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											AST_RWLIST_UNLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Copy module pointer so reference counting can keep the module from unloading */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									technology - > mod  =  module ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-29 19:24:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Find the correct position to insert the technology. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE_SAFE_BEGIN ( & bridge_technologies ,  current ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Put the highest preference tech's first in the list. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( technology - > preference  > =  current - > preference )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_RWLIST_INSERT_BEFORE_CURRENT ( technology ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE_SAFE_END ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! current )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Insert our new bridge technology to the end of the list. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_RWLIST_INSERT_TAIL ( & bridge_technologies ,  technology ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 10:46:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_verb ( 5 ,  " Registered bridge technology %s \n " ,  technology - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_technology_unregister ( struct  ast_bridge_technology  * technology )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * current ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_WRLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Ensure the bridge technology is registered before removing it */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE_SAFE_BEGIN ( & bridge_technologies ,  current ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( current  = =  technology )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_RWLIST_REMOVE_CURRENT ( entry ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 10:46:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_verb ( 5 ,  " Unregistered bridge technology %s \n " ,  technology - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-04-10 03:55:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE_SAFE_END ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  current  ?  0  :  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Put  an  action  onto  the  specified  bridge .  Don ' t  dup  the  action  frame . 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  bridge  What  to  queue  the  action  on . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  action  What  to  do . 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_queue_action_nodup ( struct  ast_bridge  * bridge ,  struct  ast_frame  * action )  
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge %s: queueing action type:%u sub:%d \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge - > uniqueid ,  action - > frametype ,  action - > subclass . integer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_INSERT_TAIL ( & bridge - > action_queue ,  action ,  frame_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_manager_service_req ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_queue_action ( struct  ast_bridge  * bridge ,  struct  ast_frame  * action )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_frame  * dup ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dup  =  ast_frdup ( action ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! dup )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_queue_action_nodup ( bridge ,  dup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  bridge_dissolve ( struct  ast_bridge  * bridge ,  int  cause )  
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_frame  action  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. frametype  =  AST_FRAME_BRIDGE_ACTION , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 19:24:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										. subclass . integer  =  BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge - > dissolved )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : already dissolved \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											BRIDGE_PRINTF_VARS ( bridge ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge - > dissolved  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 20:24:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cause  < =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cause  =  AST_CAUSE_NORMAL_CLEARING ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > cause  =  cause ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : dissolving with cause %d(%s) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( bridge ) ,  cause ,  ast_cause2str ( cause ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : kicking channel %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											BRIDGE_PRINTF_VARS ( bridge ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( bridge_channel - > chan ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_channel_leave_bridge ( bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  cause ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Must defer dissolving bridge because it is already locked. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_queue_action ( bridge ,  & action ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : DEFERRED_DISSOLVING queued.  current refcound: %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( bridge ) ,  ao2_ref ( bridge ,  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Check  if  a  bridge  should  dissolve  because  of  a  stolen  channel  and  do  it . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  bridge  Bridge  to  check . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge_channel  Stolen  channel  causing  the  check .   It  is  not  in  the  bridge  to  check  and  may  be  in  another  bridge . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  bridge  and  bridge_channel - > bridge  are  already  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_dissolve_check_stolen ( struct  ast_bridge  * bridge ,  struct  ast_bridge_channel  * bridge_channel )  
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge - > dissolved )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge_channel - > features - > usable 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ast_test_flag ( & bridge_channel - > features - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_BRIDGE_CHANNEL_FLAG_DISSOLVE_HANGUP ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* The stolen channel controlled the bridge it was stolen from. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_dissolve ( bridge ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > num_channels  <  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ast_test_flag ( & bridge - > feature_flags ,  AST_BRIDGE_FLAG_DISSOLVE_HANGUP ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  The  stolen  channel  has  not  left  enough  channels  to  keep  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  bridge  alive .   Assume  the  stolen  channel  hung  up . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_dissolve ( bridge ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-05-10 17:07:46 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-12 21:42:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Update  connected  line  information  after  a  bridge  has  been  reconfigured . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  The  bridge  itself . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_reconfigured_connected_line_update ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_party_connected_line  connected ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel  =  AST_LIST_FIRST ( & bridge - > channels ) ,  * peer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  char  data [ 1024 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									size_t  datalen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridge_channel  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										! ( bridge - > technology - > capabilities  &  ( AST_BRIDGE_CAPABILITY_1TO1MIX  |  AST_BRIDGE_CAPABILITY_NATIVE ) )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										! ( peer  =  ast_bridge_channel_peer ( bridge_channel ) )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_flag ( ast_channel_flags ( bridge_channel - > chan ) ,  AST_FLAG_ZOMBIE )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_test_flag ( ast_channel_flags ( peer - > chan ) ,  AST_FLAG_ZOMBIE )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_check_hangup_locked ( bridge_channel - > chan )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_check_hangup_locked ( peer - > chan ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_party_connected_line_init ( & connected ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_connected_line_copy_from_caller ( & connected ,  ast_channel_caller ( bridge_channel - > chan ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( datalen  =  ast_connected_line_build_data ( data ,  sizeof ( data ) ,  & connected ,  NULL ) )  ! =  ( size_t )  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_channel_queue_control_data ( peer ,  AST_CONTROL_CONNECTED_LINE ,  data ,  datalen ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( peer - > chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_connected_line_copy_from_caller ( & connected ,  ast_channel_caller ( peer - > chan ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( peer - > chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( datalen  =  ast_connected_line_build_data ( data ,  sizeof ( data ) ,  & connected ,  NULL ) )  ! =  ( size_t )  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_channel_queue_control_data ( bridge_channel ,  AST_CONTROL_CONNECTED_LINE ,  data ,  datalen ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_party_connected_line_free ( & connected ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Complete  joining  a  channel  to  the  bridge . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  bridge  What  to  operate  upon . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge_channel  What  is  joining  the  bridge  technology . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  bridge  is  already  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_channel_complete_join ( struct  ast_bridge  * bridge ,  struct  ast_bridge_channel  * bridge_channel )  
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Tell the bridge technology we are joining so they set us up */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge %s: %p(%s) is joining %s technology \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > uniqueid ,  bridge_channel ,  ast_channel_name ( bridge_channel - > chan ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > technology - > join 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  bridge - > technology - > join ( bridge ,  bridge_channel ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-13 13:20:23 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* We cannot leave the channel partially in the bridge so we must kick it out */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge %s: %p(%s) failed to join %s technology (Kicking it out) \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											bridge - > uniqueid ,  bridge_channel ,  ast_channel_name ( bridge_channel - > chan ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > technology - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel - > just_joined  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-13 13:20:23 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_channel_leave_bridge ( bridge_channel ,  BRIDGE_CHANNEL_STATE_END ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > just_joined  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-25 11:49:16 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  When  a  channel  joins  the  bridge  its  streams  need  to  be  mapped  to  the  bridge ' s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  media  types  vector .  This  way  all  streams  map  to  the  same  media  type  index  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  a  given  channel . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-06 16:15:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge_channel - > bridge - > technology - > stream_topology_changed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_channel - > bridge - > technology - > stream_topology_changed ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge_channel - > bridge ,  bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_channel_stream_map ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Complete  joining  new  channels  to  the  bridge . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  bridge  Check  for  new  channels  on  this  bridge . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  bridge  is  already  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_complete_join ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge - > dissolved )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  No  sense  in  completing  the  join  on  channels  for  a  dissolved 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  bridge .   They  are  just  going  to  be  removed  soon  anyway . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  However ,  we  do  have  reason  to  abort  here  because  the  bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  technology  may  not  be  able  to  handle  the  number  of  channels 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  still  in  the  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-08 19:38:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel_queue_deferred_frames ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! bridge_channel - > just_joined )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_channel_complete_join ( bridge ,  bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Helper function used to find the "best" bridge technology given specified capabilities */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_bridge_technology  * find_best_technology ( uint32_t  capabilities ,  struct  ast_bridge  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * current ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * best  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_RWLIST_RDLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( & bridge_technologies ,  current ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( current - > suspended )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 2 ,  " Bridge technology %s is suspended. Skipping. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												current - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ( current - > capabilities  &  capabilities ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 2 ,  " Bridge technology %s does not have any capabilities we want. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												current - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( best  & &  current - > preference  < =  best - > preference )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 2 ,  " Bridge technology %s has less preference than %s (%u <= %u). Skipping. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												current - > name ,  best - > name ,  current - > preference ,  best - > preference ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( current - > compatible  & &  ! current - > compatible ( bridge ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 2 ,  " Bridge technology %s is not compatible with properties of existing bridge. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												current - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-29 19:24:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! ast_module_running_ref ( current - > mod ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 2 ,  " Bridge technology %s is not running, skipping. \n " ,  current - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-29 19:24:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( best )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_module_unref ( best - > mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										best  =  current ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( best )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Chose bridge technology %s \n " ,  best - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  best ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  tech_deferred_destroy  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * tech ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * tech_pvt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Deferred  destruction  of  bridge  tech  private  structure . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  What  to  execute  the  action  on . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  action  Deferred  bridge  tech  destruction . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  bridge  must  not  be  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_tech_deferred_destroy ( struct  ast_bridge  * bridge ,  struct  ast_frame  * action )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  tech_deferred_destroy  * deferred  =  action - > data . ptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  dummy_bridge  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. technology  =  deferred - > tech , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. tech_pvt  =  deferred - > tech_pvt , 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-17 23:25:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										. creator  =  bridge - > creator , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. name  =  bridge - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. uniqueid  =  bridge - > uniqueid , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-06-26 21:45:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge %s: calling %s technology destructor (deferred, dummy) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dummy_bridge . uniqueid ,  dummy_bridge . technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dummy_bridge . technology - > destroy ( & dummy_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_module_unref ( dummy_bridge . technology - > mod ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Handle  bridge  action  frame . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  bridge  What  to  execute  the  action  on . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  action  What  to  do . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  bridge  is  already  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-19 16:47:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ note  Can  be  called  by  the  bridge  destructor 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_action_bridge ( struct  ast_bridge  * bridge ,  struct  ast_frame  * action )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#if 0 	/* In case we need to know when the destructor is calling us. */
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  in_destructor  =  ! ao2_ref ( bridge ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( action - > subclass . integer )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 19:24:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  BRIDGE_CHANNEL_ACTION_DEFERRED_TECH_DESTROY : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_tech_deferred_destroy ( bridge ,  action ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 19:24:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > v_table - > dissolving ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Unexpected deferred action type.  Should never happen. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Do  any  pending  bridge  actions . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  What  to  do  actions  on . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  bridge  is  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  Can  be  called  by  the  bridge  destructor . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_handle_actions ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_frame  * action ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( ( action  =  AST_LIST_REMOVE_HEAD ( & bridge - > action_queue ,  frame_list ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  ( action - > frametype )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  AST_FRAME_BRIDGE_ACTION : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge_action_bridge ( bridge ,  action ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Unexpected deferred frame type.  Should never happen. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_frfree ( action ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  destroy_bridge ( void  * obj )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge  =  obj ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-21 17:48:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : actually destroying %s bridge, nobody wants it anymore \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( bridge ) ,  bridge - > v_table - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge - > construction_completed )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_topics_destroy ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Do any pending actions in the context of destruction. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_handle_actions ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* There should not be any channels left in the bridge. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( AST_LIST_EMPTY ( & bridge - > channels ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge %s: calling %s bridge destructor \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > uniqueid ,  bridge - > v_table - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > v_table - > destroy ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Pass off the bridge to the technology to destroy if needed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > technology )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge %s: calling %s technology stop \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > uniqueid ,  bridge - > technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bridge - > technology - > stop )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > technology - > stop ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge %s: calling %s technology destructor \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > uniqueid ,  bridge - > technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bridge - > technology - > destroy )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > technology - > destroy ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_module_unref ( bridge - > technology - > mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > technology  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-25 11:49:16 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_VECTOR_FREE ( & bridge - > media_types ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-03-13 01:12:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge - > callid  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cleanup_video_mode ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 13:49:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : destroyed \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( bridge ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-17 23:25:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_string_field_free_memory ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_cleanup ( bridge - > current_snapshot ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge - > current_snapshot  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_bridge  * bridge_register ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										SCOPED_MUTEX ( lock ,  & bridge_init_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Although  bridge_base_init ( )  should  have  already  checked  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  an  existing  bridge  with  the  same  uniqueid ,  bridge_base_init ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  and  bridge_register ( )  are  two  separate  public  APIs  so  we  need 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  to  check  again  here . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge  * existing  =  ast_bridge_find_by_id ( bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( existing )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : already registered \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												BRIDGE_PRINTF_VARS ( bridge ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( existing ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_destroy ( bridge ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : registering \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											BRIDGE_PRINTF_VARS ( bridge ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge - > construction_completed  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-04-11 12:43:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_publish_state ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-04-11 12:43:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! ao2_link ( bridges ,  bridge ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : failed to link \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												BRIDGE_PRINTF_VARS ( bridge ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_bridge_destroy ( bridge ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											bridge  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_bridge  * bridge_alloc ( size_t  size ,  const  struct  ast_bridge_methods  * v_table )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 18:45:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Check v_table that all methods are present. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! v_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! v_table - > name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! v_table - > destroy 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! v_table - > dissolving 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! v_table - > push 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! v_table - > pull 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! v_table - > notify_masquerade 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! v_table - > get_merge_priority )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Virtual method table for bridge class %s not complete. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											v_table  & &  v_table - > name  ?  v_table - > name  :  " <unknown> " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge  =  ao2_alloc ( size ,  destroy_bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-17 23:25:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_string_field_init ( bridge ,  80 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_cleanup ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-17 23:25:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > v_table  =  v_table ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-25 11:49:16 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_VECTOR_INIT ( & bridge - > media_types ,  AST_MEDIA_TYPE_END ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												uniqueid: channel linkedid, ami, ari object creation with id's
Much needed was a way to assign id to objects on creation, and
much change was necessary to accomplish it.  Channel uniqueids
and linkedids are split into separate string and creation time
components without breaking linkedid propgation.  This allowed
the uniqueid to be specified by the user interface - and those
values are now carried through to channel creation, adding the
assignedids value to every function in the chain including the
channel drivers. For local channels, the second channel can be
specified or left to default to a ;2 suffix of first.  In ARI,
bridge, playback, and snoop objects can also be created with a
specified uniqueid.
Along the way, the args order to allocating channels was fixed
in chan_mgcp and chan_gtalk, and linkedid is no longer lost as
masquerade occurs.
(closes issue ASTERISK-23120)
Review: https://reviewboard.asterisk.org/r/3191/
........
Merged revisions 410157 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410158 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-03-07 15:47:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_bridge  * bridge_base_init ( struct  ast_bridge  * self ,  uint32_t  capabilities ,  unsigned  int  flags ,  const  char  * creator ,  const  char  * name ,  const  char  * id )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-12-17 23:25:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  uuid_hold [ AST_UUID_STR_LEN ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! self )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  We  need  to  ensure  that  another  bridge  with  the  same  uniqueid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  doesn ' t  get  created  before  the  previous  bridge ' s  destructor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  has  run  and  deleted  the  existing  topic . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										SCOPED_MUTEX ( lock ,  & bridge_init_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ast_strlen_zero ( id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ast_bridge_topic_exists ( id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_WARNING ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : already registered \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													BRIDGE_PRINTF_VARS ( self ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_bridge_destroy ( self ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_string_field_set ( self ,  uniqueid ,  id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_uuid_generate_str ( uuid_hold ,  AST_UUID_STR_LEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_string_field_set ( self ,  uniqueid ,  uuid_hold ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ( flags  &  AST_BRIDGE_FLAG_INVISIBLE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( bridge_topics_init ( self )  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_WARNING ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : Could not initialize topics \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													BRIDGE_PRINTF_VARS ( self ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ao2_ref ( self ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												uniqueid: channel linkedid, ami, ari object creation with id's
Much needed was a way to assign id to objects on creation, and
much change was necessary to accomplish it.  Channel uniqueids
and linkedids are split into separate string and creation time
components without breaking linkedid propgation.  This allowed
the uniqueid to be specified by the user interface - and those
values are now carried through to channel creation, adding the
assignedids value to every function in the chain including the
channel drivers. For local channels, the second channel can be
specified or left to default to a ;2 suffix of first.  In ARI,
bridge, playback, and snoop objects can also be created with a
specified uniqueid.
Along the way, the args order to allocating channels was fixed
in chan_mgcp and chan_gtalk, and linkedid is no longer lost as
masquerade occurs.
(closes issue ASTERISK-23120)
Review: https://reviewboard.asterisk.org/r/3191/
........
Merged revisions 410157 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410158 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-03-07 15:47:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-12-17 23:25:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_string_field_set ( self ,  creator ,  creator ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_strlen_zero ( creator ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_string_field_set ( self ,  name ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : base_init \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( self ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-17 23:25:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_set_flag ( & self - > feature_flags ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > allowed_capabilities  =  capabilities ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Use our helper function to find the "best" bridge technology. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > technology  =  find_best_technology ( capabilities ,  self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! self - > technology )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Bridge %s: Could not create class %s.  No technology to support it. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > uniqueid ,  self - > v_table - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( self ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Pass off the bridge to the technology to manipulate if needed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge %s: calling %s technology constructor \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > uniqueid ,  self - > technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( self - > technology - > create  & &  self - > technology - > create ( self ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Bridge %s: failed to setup bridge technology %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > uniqueid ,  self - > technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( self ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge %s: calling %s technology start \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > uniqueid ,  self - > technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( self - > technology - > start  & &  self - > technology - > start ( self ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Bridge %s: failed to start bridge technology %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > uniqueid ,  self - > technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( self ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-09 14:27:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ( flags  &  AST_BRIDGE_FLAG_INVISIBLE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ast_bridge_topic ( self ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( self ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:32:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self - > creationtime  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : base_init complete \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( self ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:32:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  self ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  ast_bridge  base  class  destructor . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  self  Bridge  to  operate  upon . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  Stub  because  of  nothing  to  do . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_base_destroy ( struct  ast_bridge  * self )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : destroying bridge (noop) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( self ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  The  bridge  is  being  dissolved . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  self  Bridge  to  operate  upon . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_base_dissolving ( struct  ast_bridge  * self )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : unlinking bridge.  Refcount: %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( self ) ,  ao2_ref ( self ,  0 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlink ( bridges ,  self ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : unlinked bridge.  Refcount: %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( self ) ,  ao2_ref ( self ,  0 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  ast_bridge  base  push  method . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  self  Bridge  to  operate  upon . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge_channel  Bridge  channel  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  0  on  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  on  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_base_push ( struct  ast_bridge  * self ,  struct  ast_bridge_channel  * bridge_channel ,  struct  ast_bridge_channel  * swap )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  ast_bridge  base  pull  method . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  self  Bridge  to  operate  upon . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge_channel  Bridge  channel  to  pull . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  self  is  already  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_base_pull ( struct  ast_bridge  * self ,  struct  ast_bridge_channel  * bridge_channel )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_features_remove ( bridge_channel - > features ,  AST_BRIDGE_HOOK_REMOVE_ON_PULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  ast_bridge  base  notify_masquerade  method . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  self  Bridge  to  operate  upon . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge_channel  Bridge  channel  that  was  masqueraded . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  self  is  already  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_base_notify_masquerade ( struct  ast_bridge  * self ,  struct  ast_bridge_channel  * bridge_channel )  
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self - > reconfigured  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Get  the  merge  priority  of  this  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  self  Bridge  to  operate  upon . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  self  is  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  Merge  priority 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_base_get_merge_priority ( struct  ast_bridge  * self )  
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-29 23:03:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  ast_bridge  base  push_peek  method . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  13.2 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  self  Bridge  to  operate  upon . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge_channel  Bridge  channel  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  0  on  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  on  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_base_push_peek ( struct  ast_bridge  * self ,  struct  ast_bridge_channel  * bridge_channel ,  struct  ast_bridge_channel  * swap )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_bridge_methods  ast_bridge_base_v_table  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " base " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. destroy  =  bridge_base_destroy , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. dissolving  =  bridge_base_dissolving , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. push  =  bridge_base_push , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. pull  =  bridge_base_pull , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. notify_masquerade  =  bridge_base_notify_masquerade , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. get_merge_priority  =  bridge_base_get_merge_priority , 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-29 23:03:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. push_peek  =  bridge_base_push_peek , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												uniqueid: channel linkedid, ami, ari object creation with id's
Much needed was a way to assign id to objects on creation, and
much change was necessary to accomplish it.  Channel uniqueids
and linkedids are split into separate string and creation time
components without breaking linkedid propgation.  This allowed
the uniqueid to be specified by the user interface - and those
values are now carried through to channel creation, adding the
assignedids value to every function in the chain including the
channel drivers. For local channels, the second channel can be
specified or left to default to a ;2 suffix of first.  In ARI,
bridge, playback, and snoop objects can also be created with a
specified uniqueid.
Along the way, the args order to allocating channels was fixed
in chan_mgcp and chan_gtalk, and linkedid is no longer lost as
masquerade occurs.
(closes issue ASTERISK-23120)
Review: https://reviewboard.asterisk.org/r/3191/
........
Merged revisions 410157 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410158 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-03-07 15:47:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_bridge  * ast_bridge_base_new ( uint32_t  capabilities ,  unsigned  int  flags ,  const  char  * creator ,  const  char  * name ,  const  char  * id )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									void  * bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge  =  bridge_alloc ( sizeof ( struct  ast_bridge ) ,  & ast_bridge_base_v_table ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												uniqueid: channel linkedid, ami, ari object creation with id's
Much needed was a way to assign id to objects on creation, and
much change was necessary to accomplish it.  Channel uniqueids
and linkedids are split into separate string and creation time
components without breaking linkedid propgation.  This allowed
the uniqueid to be specified by the user interface - and those
values are now carried through to channel creation, adding the
assignedids value to every function in the chain including the
channel drivers. For local channels, the second channel can be
specified or left to default to a ;2 suffix of first.  In ARI,
bridge, playback, and snoop objects can also be created with a
specified uniqueid.
Along the way, the args order to allocating channels was fixed
in chan_mgcp and chan_gtalk, and linkedid is no longer lost as
masquerade occurs.
(closes issue ASTERISK-23120)
Review: https://reviewboard.asterisk.org/r/3191/
........
Merged revisions 410157 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410158 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-03-07 15:47:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge  =  bridge_base_init ( bridge ,  capabilities ,  flags ,  creator ,  name ,  id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge  =  bridge_register ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_destroy ( struct  ast_bridge  * bridge ,  int  cause )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : destroying.  current refcount: %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( bridge ) ,  ao2_ref ( bridge ,  0 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_dissolve ( bridge ,  cause ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge  "  BRIDGE_PRINTF_SPEC  " : unreffing.  current refcount: %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_PRINTF_VARS ( bridge ) ,  ao2_ref ( bridge ,  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_ref ( bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Perform  the  smart  bridge  operation . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  bridge  Work  on  this  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ details 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Basically  see  if  a  new  bridge  technology  should  be  used  instead 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  of  the  current  one . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  bridge  is  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ retval  0  on  success . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  on  error . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  smart_bridge_operation ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uint32_t  new_capabilities ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * new_technology ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * old_technology  =  bridge - > technology ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_frame  * deferred_action ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  dummy_bridge  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. technology  =  bridge - > technology , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. tech_pvt  =  bridge - > tech_pvt , 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-17 23:25:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										. creator  =  bridge - > creator , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. name  =  bridge - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. uniqueid  =  bridge - > uniqueid , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > dissolved )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge %s is dissolved, not performing smart bridge operation. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Determine new bridge technology capabilities needed. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( 2  <  bridge - > num_channels )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_capabilities  =  AST_BRIDGE_CAPABILITY_MULTIMIX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_capabilities  & =  bridge - > allowed_capabilities ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_capabilities  =  AST_BRIDGE_CAPABILITY_NATIVE  |  AST_BRIDGE_CAPABILITY_1TO1MIX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_capabilities  & =  bridge - > allowed_capabilities ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! new_capabilities 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  ( bridge - > allowed_capabilities  &  AST_BRIDGE_CAPABILITY_MULTIMIX ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Allow switching between different multimix bridge technologies. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											new_capabilities  =  AST_BRIDGE_CAPABILITY_MULTIMIX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Find a bridge technology to satisfy the new capabilities. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									new_technology  =  find_best_technology ( new_capabilities ,  bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! new_technology )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  is_compatible  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( old_technology - > compatible )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											is_compatible  =  old_technology - > compatible ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( old_technology - > capabilities  &  AST_BRIDGE_CAPABILITY_MULTIMIX )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											is_compatible  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( bridge - > num_channels  < =  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  ( old_technology - > capabilities  &  AST_BRIDGE_CAPABILITY_1TO1MIX ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											is_compatible  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( is_compatible )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " Bridge %s could not get a new technology, staying with old technology. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Bridge %s has no technology available to support it. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( new_technology  = =  old_technology )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge %s is already using the new technology. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_module_unref ( old_technology - > mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( old_technology - > destroy )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  tech_deferred_destroy  deferred_tech_destroy  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											. tech  =  dummy_bridge . technology , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											. tech_pvt  =  dummy_bridge . tech_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_frame  action  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											. frametype  =  AST_FRAME_BRIDGE_ACTION , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 19:24:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											. subclass . integer  =  BRIDGE_CHANNEL_ACTION_DEFERRED_TECH_DESTROY , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											. data . ptr  =  & deferred_tech_destroy , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											. datalen  =  sizeof ( deferred_tech_destroy ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 *  We  need  to  defer  the  bridge  technology  destroy  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  because  we  have  the  bridge  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										deferred_action  =  ast_frdup ( & action ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! deferred_action )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_module_unref ( new_technology - > mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										deferred_action  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  We  are  now  committed  to  changing  the  bridge  technology .   We 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  must  not  release  the  bridge  lock  until  we  have  installed  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  new  bridge  technology . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_verb ( 4 ,  " Bridge %s: switching from %s technology to %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > uniqueid ,  old_technology - > name ,  new_technology - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Since  we  are  soon  going  to  pass  this  bridge  to  a  new 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  technology  we  need  to  NULL  out  the  tech_pvt  pointer  but 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  don ' t  worry  as  it  still  exists  in  dummy_bridge ,  ditto  for  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  old  technology . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > tech_pvt  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > technology  =  new_technology ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 21:40:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Setup the new bridge technology. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge %s: calling %s technology constructor \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > uniqueid ,  new_technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( new_technology - > create  & &  new_technology - > create ( bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Bridge %s: failed to setup bridge technology %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > uniqueid ,  new_technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > tech_pvt  =  dummy_bridge . tech_pvt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > technology  =  dummy_bridge . technology ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_module_unref ( new_technology - > mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 21:40:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-10-10 20:48:46 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* To ensure that things are sane for the old technology move the channels it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  expects  to  the  dummy  bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_BEGIN ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bridge_channel - > just_joined )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge %s: moving %p(%s) to dummy bridge temporarily \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > uniqueid ,  bridge_channel ,  ast_channel_name ( bridge_channel - > chan ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_REMOVE_CURRENT ( entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_INSERT_TAIL ( & dummy_bridge . channels ,  bridge_channel ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dummy_bridge . num_channels + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( & bridge_channel - > features - > feature_flags ,  AST_BRIDGE_CHANNEL_FLAG_LONELY ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dummy_bridge . num_lonely + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! bridge_channel - > suspended )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dummy_bridge . num_active + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_END ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Take all the channels out of the old technology */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_BEGIN ( & dummy_bridge . channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge %s: %p(%s) is leaving %s technology (dummy) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dummy_bridge . uniqueid ,  bridge_channel ,  ast_channel_name ( bridge_channel - > chan ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											old_technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( old_technology - > leave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											old_technology - > leave ( & dummy_bridge ,  bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_REMOVE_CURRENT ( entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_INSERT_TAIL ( & bridge - > channels ,  bridge_channel ,  entry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dummy_bridge . num_channels - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( & bridge_channel - > features - > feature_flags ,  AST_BRIDGE_CHANNEL_FLAG_LONELY ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dummy_bridge . num_lonely - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! bridge_channel - > suspended )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dummy_bridge . num_active - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_END ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge %s: calling %s technology stop \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dummy_bridge . uniqueid ,  old_technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( old_technology - > stop )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										old_technology - > stop ( & dummy_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-10-10 20:48:46 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Add any new channels or re-add existing channels to the bridge. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_channel_complete_join ( bridge ,  bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Bridge %s: calling %s technology start \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > uniqueid ,  new_technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( new_technology - > start  & &  new_technology - > start ( bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " Bridge %s: failed to start bridge technology %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > uniqueid ,  new_technology - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Now  that  all  the  channels  have  been  moved  over  we  need  to  get 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  rid  of  all  the  information  the  old  technology  may  have  left 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  around . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( old_technology - > destroy )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge %s: deferring %s technology destructor \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dummy_bridge . uniqueid ,  old_technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_queue_action_nodup ( bridge ,  deferred_action ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Bridge %s: calling %s technology destructor \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dummy_bridge . uniqueid ,  old_technology - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_module_unref ( old_technology - > mod ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Bridge  channel  to  check  if  a  BRIDGE_PLAY_SOUND  needs  to  be  played . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge_channel  What  to  check . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  check_bridge_play_sound ( struct  ast_bridge_channel  * bridge_channel )  
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * play_file ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 00:16:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_lock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									play_file  =  pbx_builtin_getvar_helper ( bridge_channel - > chan ,  " BRIDGE_PLAY_SOUND " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_strlen_zero ( play_file ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										play_file  =  ast_strdupa ( play_file ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pbx_builtin_setvar_helper ( bridge_channel - > chan ,  " BRIDGE_PLAY_SOUND " ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										play_file  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 00:16:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_unlock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-12 21:42:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( play_file )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_channel_queue_playfile ( bridge_channel ,  NULL ,  play_file ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-12 21:42:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Check  for  any  BRIDGE_PLAY_SOUND  channel  variables  in  the  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  What  to  operate  on . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  the  bridge  is  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  check_bridge_play_sounds ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										check_bridge_play_sound ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-01 16:11:07 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_vars_set ( struct  ast_channel  * chan ,  const  char  * name ,  const  char  * pvtid )  
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-10-02 16:23:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_stage_snapshot ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									pbx_builtin_setvar_helper ( chan ,  " BRIDGEPEER " ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pbx_builtin_setvar_helper ( chan ,  " BRIDGEPVTCALLID " ,  pvtid ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 16:23:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_stage_snapshot_done ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Set  BRIDGEPEER  and  BRIDGEPVTCALLID  channel  variables  in  a  2  party  bridge . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  c0  Party  of  the  first  part . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  c1  Party  of  the  second  part . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  the  bridge  is  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  The  bridge  is  expected  to  have  exactly  two  parties . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  set_bridge_peer_vars_2party ( struct  ast_channel  * c0 ,  struct  ast_channel  * c1 )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * c0_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * c1_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * c0_pvtid  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * c1_pvtid  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define UPDATE_BRIDGE_VARS_GET(chan, name, pvtid)									\ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									do  { 																			\
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										name  =  ast_strdupa ( ast_channel_name ( chan ) ) ; 									\
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_channel_tech ( chan ) - > get_pvt_uniqueid )  { 								\
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pvtid  =  ast_strdupa ( ast_channel_tech ( chan ) - > get_pvt_uniqueid ( chan ) ) ; 	\
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 																			\
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  while  ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( c1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									UPDATE_BRIDGE_VARS_GET ( c1 ,  c1_name ,  c1_pvtid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( c1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( c0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-01 16:11:07 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_vars_set ( c0 ,  c1_name ,  c1_pvtid ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									UPDATE_BRIDGE_VARS_GET ( c0 ,  c0_name ,  c0_pvtid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( c0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( c1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-01 16:11:07 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_vars_set ( c1 ,  c0_name ,  c0_pvtid ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_unlock ( c1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Fill  the  BRIDGEPEER  value  buffer  with  a  comma  separated  list  of  channel  names . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  buf  Buffer  to  fill .   The  caller  must  guarantee  the  buffer  is  large  enough . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cur_idx  Which  index  into  names [ ]  to  skip . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  names  Channel  names  to  put  in  the  buffer . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  num_names  Number  of  names  in  the  array . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  fill_bridgepeer_buf ( char  * buf ,  unsigned  int  cur_idx ,  const  char  * names [ ] ,  unsigned  int  num_names )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  need_separator  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * src ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * pos ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									pos  =  buf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( idx  =  0 ;  idx  <  num_names ;  + + idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( idx  = =  cur_idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( need_separator )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* pos + +  =  ' , ' ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										need_separator  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Copy name into buffer. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										src  =  names [ idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( * src )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* pos + +  =  * src + + ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* pos  =  ' \0 ' ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Set  BRIDGEPEER  and  BRIDGEPVTCALLID  channel  variables  in  a  multi - party  bridge . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  bridge  What  to  operate  on . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  the  bridge  is  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  The  bridge  is  expected  to  have  more  than  two  parties . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  set_bridge_peer_vars_multiparty ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Set  a  maximum  number  of  channel  names  for  the  BRIDGEPEER 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  list .   The  plus  one  is  for  the  current  channel  which  is  not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  put  in  the  list . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define MAX_BRIDGEPEER_CHANS	(10 + 1) 
  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  int  idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  num_names ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * * names ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * buf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get first MAX_BRIDGEPEER_CHANS channel names. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									num_names  =  MIN ( bridge - > num_channels ,  MAX_BRIDGEPEER_CHANS ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									names  =  ast_alloca ( num_names  *  sizeof ( * names ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									idx  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( num_names  < =  idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_channel_lock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										names [ idx + + ]  =  ast_strdupa ( ast_channel_name ( bridge_channel - > chan ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Determine maximum buf size needed. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									len  =  num_names ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( idx  =  0 ;  idx  <  num_names ;  + + idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										len  + =  strlen ( names [ idx ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									buf  =  ast_alloca ( len ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Set the bridge channel variables. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									idx  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									buf [ 0 ]  =  ' \0 ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( idx  <  num_names )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											fill_bridgepeer_buf ( buf ,  idx ,  names ,  num_names ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										+ + idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_lock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-01 16:11:07 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_vars_set ( bridge_channel - > chan ,  buf ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_channel_unlock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Set  BRIDGEPEER  and  BRIDGEPVTCALLID  channel  variables  in  a  holding  bridge . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  bridge  What  to  operate  on . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  the  bridge  is  already  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  set_bridge_peer_vars_holding ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_lock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-01 16:11:07 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_vars_set ( bridge_channel - > chan ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_channel_unlock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Set  BRIDGEPEER  and  BRIDGEPVTCALLID  channel  variables  in  the  bridge . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  bridge  What  to  operate  on . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  On  entry ,  the  bridge  is  already  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  set_bridge_peer_vars ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge - > technology - > capabilities  &  AST_BRIDGE_CAPABILITY_HOLDING )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_bridge_peer_vars_holding ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > num_channels  <  2 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > num_channels  = =  2 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_bridge_peer_vars_2party ( AST_LIST_FIRST ( & bridge - > channels ) - > chan , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_LIST_LAST ( & bridge - > channels ) - > chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_bridge_peer_vars_multiparty ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  bridge_reconfigured ( struct  ast_bridge  * bridge ,  unsigned  int  colp_update )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge - > reconfigured )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge - > reconfigured  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & bridge - > feature_flags ,  AST_BRIDGE_FLAG_SMART ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  smart_bridge_operation ( bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Smart bridge failed. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_dissolve ( bridge ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_complete_join ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge - > dissolved )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									check_bridge_play_sounds ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									set_bridge_peer_vars ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_publish_state ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( colp_update )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_reconfigured_connected_line_update ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_bridge_channel  * bridge_find_channel ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bridge_channel - > chan  = =  chan )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Replace chan_agent with app_agent_pool.
The ill conceived chan_agent is no more.  It is now replaced by
app_agent_pool.
Agents login using the AgentLogin() application as before.  The
AgentLogin() application no longer does any authentication.
Authentication is now the responsibility of the dialplan.  (Besides, the
authentication done by chan_agent did not match what the voice prompts
asked for.)
Sample extensions.conf
[login]
; Sample agent 1001 login
; Set COLP for in between calls so the agent does not see the last caller COLP.
exten => 1001,1,Set(CONNECTEDLINE(all)="Agent Waiting" <1001>)
; Give the agent DTMF transfer and disconnect features when connected to a caller.
same => n,Set(CHANNEL(dtmf-features)=TX)
same => n,AgentLogin(1001)
same => n,NoOp(AGENT_STATUS is ${AGENT_STATUS})
same => n,Hangup()
[caller]
; Sample caller direct connect to agent 1001
exten => 800,1,AgentRequest(1001)
same => n,NoOp(AGENT_STATUS is ${AGENT_STATUS})
same => n,Hangup()
; Sample caller going through a Queue to agent 1001
exten => 900,1,Queue(agent_q)
same => n,Hangup()
Sample queues.conf
[agent_q]
member => Local/800@caller,,SuperAgent,Agent:1001
Under the hood operation overview:
1) Logged in agents wait for callers in an agents holding bridge.
2) Caller requests an agent using AgentRequest()
3) A basic bridge is created, the agent is notified, and caller joins the
   basic bridge to wait for the agent.
4) The agent is either automatically connected to the caller or must ack
   the call to connect.
5) The agent is moved from the agents holding bridge to the basic bridge.
6) The agent and caller talk.
7) The connection is ended by either party.
8) The agent goes back to the agents holding bridge.
To avoid some locking issues with the agent holding bridge, I needed to
make some changes to the after bridge callback support.  The after bridge
callback is now a list of requested callbacks with the last to be added
the only active callback.  The after bridge callback for failed callbacks
will always happen in the channel thread when the channel leaves the
bridging system or is destroyed.
(closes issue ASTERISK-21554)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2657/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394417 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-15 23:20:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_notify_masquerade ( struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Safely get the bridge_channel pointer for the chan. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel  =  ast_channel_get_bridge_channel ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridge_channel )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Not in a bridge */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_channel_lock_bridge ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge  =  bridge_channel - > bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge_channel  = =  bridge_find_channel ( bridge ,  chan ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 16:46:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  XXX  ASTERISK - 22366  this  needs  more  work .   The  channels  need 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  to  be  made  compatible  again  if  the  formats  change .  The 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  bridge_channel  thread  needs  to  monitor  for  this  case . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* The channel we want to notify is still in a bridge. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > v_table - > notify_masquerade ( bridge ,  bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-12 21:42:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_reconfigured ( bridge ,  1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( bridge_channel ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Internal  bridge  impart  wait  condition  and  associated  conditional . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  bridge_channel_impart_cond  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_ENTRY ( bridge_channel_impart_cond )  node ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Lock for the data structure */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_t  lock ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Wait condition */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_t  cond ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Wait until done */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  done ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_LIST_HEAD_NOLOCK ( bridge_channel_impart_ds_head ,  bridge_channel_impart_cond ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Signal  imparting  threads  to  wake  up . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  13.9 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  ds_head  List  of  imparting  threads  to  wake  up . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_channel_impart_ds_head_signal ( struct  bridge_channel_impart_ds_head  * ds_head )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ds_head )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  bridge_channel_impart_cond  * cond ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( ( cond  =  AST_LIST_REMOVE_HEAD ( ds_head ,  node ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_mutex_lock ( & cond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cond - > done  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cond_signal ( & cond - > cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_mutex_unlock ( & cond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_channel_impart_ds_head_dtor ( void  * doomed )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel_impart_ds_head_signal ( doomed ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_free ( doomed ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Fixup  the  bridge  impart  datastore . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  13.9 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  Bridge  impart  datastore  data  to  fixup  from  old_chan . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  old_chan  The  datastore  is  moving  from  this  channel . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  new_chan  The  datastore  is  moving  to  this  channel . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_channel_impart_ds_head_fixup ( void  * data ,  struct  ast_channel  * old_chan ,  struct  ast_channel  * new_chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Signal  any  waiting  impart  threads .   The  masquerade  is  going  to  kill 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  old_chan  and  we  don ' t  need  to  be  waiting  on  new_chan . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel_impart_ds_head_signal ( data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  struct  ast_datastore_info  bridge_channel_impart_ds_info  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. type  =  " bridge-impart-ds " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. destroy  =  bridge_channel_impart_ds_head_dtor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. chan_fixup  =  bridge_channel_impart_ds_head_fixup , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Add  impart  wait  datastore  conditional  to  channel . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  13.9 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan  Channel  to  add  the  impart  wait  conditional . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cond  Imparting  conditional  to  add . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  on  success . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  on  error . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_channel_impart_add ( struct  ast_channel  * chan ,  struct  bridge_channel_impart_cond  * cond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_datastore  * datastore ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_channel_impart_ds_head  * ds_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									datastore  =  ast_channel_datastore_find ( chan ,  & bridge_channel_impart_ds_info ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! datastore )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										datastore  =  ast_datastore_alloc ( & bridge_channel_impart_ds_info ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! datastore )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ds_head  =  ast_calloc ( 1 ,  sizeof ( * ds_head ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ds_head )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_datastore_free ( datastore ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										datastore - > data  =  ds_head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_datastore_add ( chan ,  datastore ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ds_head  =  datastore - > data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( ds_head  ! =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_INSERT_TAIL ( ds_head ,  cond ,  node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  bridge_channel_impart_signal ( struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_datastore  * datastore ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									datastore  =  ast_channel_datastore_find ( chan ,  & bridge_channel_impart_ds_info ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( datastore )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_channel_impart_ds_head_signal ( datastore - > data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Block  imparting  channel  thread  until  signaled . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  13.9 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cond  Imparting  conditional  to  wait  for . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_channel_impart_wait ( struct  bridge_channel_impart_cond  * cond )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_lock ( & cond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ! cond - > done )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cond_wait ( & cond - > cond ,  & cond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_unlock ( & cond - > lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
									
										
										
										
											2013-08-15 18:20:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  XXX  ASTERISK - 21271  make  ast_bridge_join ( )  require  features  to  be  allocated  just  like  ast_bridge_impart ( )  and  not  expect  the  struct  back . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  change  is  really  going  to  break  ConfBridge .   All  other 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  users  are  easily  changed .   However ,  it  is  needed  so  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  bridging  code  can  manipulate  features  on  all  channels 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  consistently  no  matter  how  they  joined . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Need  to  update  the  features  parameter  doxygen  when  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  change  is  made  to  be  like  ast_bridge_impart ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 16:34:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_join ( struct  ast_bridge  * bridge ,  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_channel  * chan , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * swap , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_features  * features , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_tech_optimizations  * tech_args , 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-13 22:19:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_join_flags  flags ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-06 13:23:24 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									SCOPE_TRACE ( 1 ,  " %s Bridge: %s \n " ,  ast_channel_name ( chan ) ,  bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel  =  bridge_channel_internal_alloc ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-13 22:19:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( flags  &  AST_BRIDGE_JOIN_PASS_REFERENCE )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_ref ( bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridge_channel )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-22 19:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_t_cleanup ( swap ,  " Error exit: bridge_channel alloc failed " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 16:34:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										goto  join_exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-15 18:20:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* XXX ASTERISK-21271 features cannot be NULL when passed in. When it is changed to allocated we can do like ast_bridge_impart() and allocate one. */  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_assert ( features  ! =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! features )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( bridge_channel ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-22 19:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_t_cleanup ( swap ,  " Error exit: features is NULL " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 16:34:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										goto  join_exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( tech_args )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_channel - > tech_args  =  * tech_args ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( ast_channel_flags ( chan ) ,  AST_FLAG_ZOMBIE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_internal_bridge_channel_set ( chan ,  bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > thread  =  pthread_self ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > chan  =  chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > swap  =  swap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > features  =  features ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-13 22:19:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > inhibit_colp  =  ! ! ( flags  &  AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-29 23:03:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* allow subclass to peek at upcoming push operation */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > v_table - > push_peek  & &  ! res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_channel  * bcswap  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bridge_channel - > swap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bcswap  =  bridge_find_channel ( bridge ,  bridge_channel - > swap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  bridge - > v_table - > push_peek ( bridge ,  bridge_channel ,  bcswap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! res )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  bridge_channel_internal_join ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Cleanup all the data in the bridge channel after it leaves the bridge. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_internal_bridge_channel_set ( chan ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-31 11:14:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Due to a race condition, we lock the bridge channel here for ast_bridge_channel_get_chan */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_lock ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > chan  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-31 11:14:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-22 19:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If bridge_channel->swap is not NULL then the join failed. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_t_cleanup ( bridge_channel - > swap ,  " Bridge complete: join failed " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > swap  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > features  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( bridge_channel ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-09-15 09:43:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								join_exit :  
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_run_after_callback ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel_impart_signal ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ( ast_channel_softhangup_internal_flag ( chan )  &  AST_SOFTHANGUP_ASYNCGOTO ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  ! ast_bridge_setup_after_goto ( chan ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Claim the after bridge goto is an async goto destination. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_softhangup_nolock ( chan ,  AST_SOFTHANGUP_ASYNCGOTO ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 16:34:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Thread responsible for imparted bridged channels to be departed */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * bridge_channel_depart_thread ( void  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel  =  data ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-01 04:17:02 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge_channel - > callid )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_callid_threadassoc_add ( bridge_channel - > callid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-09-01 04:17:02 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  bridge_channel_internal_join ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-22 19:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  cleanup 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  If  bridge_channel - > swap  is  not  NULL  then  the  join  failed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_t_cleanup ( bridge_channel - > swap ,  " Bridge complete: Departable impart join failed " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > swap  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_features_destroy ( bridge_channel - > features ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > features  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-09-01 04:17:02 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_discard_after_callback ( bridge_channel - > chan , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  ?  AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED  :  AST_BRIDGE_AFTER_CB_REASON_DEPART ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If join failed there will be impart threads waiting. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel_impart_signal ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_discard_after_goto ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Thread responsible for independent imparted bridged channels */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * bridge_channel_ind_thread ( void  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel  =  data ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_channel  * chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge_channel - > callid )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_callid_threadassoc_add ( bridge_channel - > callid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel_internal_join ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									chan  =  bridge_channel - > chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* cleanup */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_internal_bridge_channel_set ( chan ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-31 11:14:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Lock here for ast_bridge_channel_get_chan */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_lock ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > chan  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-31 11:14:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-22 19:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If bridge_channel->swap is not NULL then the join failed. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_t_cleanup ( bridge_channel - > swap ,  " Bridge complete: Independent impart join failed " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > swap  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_features_destroy ( bridge_channel - > features ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > features  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( bridge_channel ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_run_after_callback ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If join failed there will be impart threads waiting. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel_impart_signal ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_run_after_goto ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  bridge_impart_internal ( struct  ast_bridge  * bridge ,  
						 
					
						
							
								
									
										
										
										
											2013-09-13 22:19:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_channel  * chan , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * swap , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_features  * features , 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_impart_flags  flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_channel_impart_cond  * cond ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Imparted channels cannot have a PBX. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_channel_pbx ( chan ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_WARNING ,  " Channel %s has a PBX thread and cannot be imparted into bridge %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ,  bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-28 16:41:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_features_destroy ( features ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Supply an empty features structure if the caller did not. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! features )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										features  =  ast_bridge_features_new ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! features )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Try to allocate a structure for the bridge channel */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel  =  bridge_channel_internal_alloc ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge_channel )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_features_destroy ( features ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( ast_channel_flags ( chan ) ,  AST_FLAG_ZOMBIE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_NOTICE ,  " Channel %s is a zombie and cannot be imparted into bridge %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ,  bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_internal_bridge_channel_set ( chan ,  bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > chan  =  chan ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-22 19:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > swap  =  ao2_t_bump ( swap ,  " Setting up bridge impart " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > features  =  features ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-13 22:19:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > inhibit_colp  =  ! ! ( flags  &  AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > depart_wait  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										( flags  &  AST_BRIDGE_IMPART_CHAN_MASK )  = =  AST_BRIDGE_IMPART_CHAN_DEPARTABLE ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel - > callid  =  ast_read_threadstorage_callid ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-29 23:03:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* allow subclass to peek at swap channel before it can hangup */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > v_table - > push_peek  & &  ! res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_channel  * bcswap  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bridge_channel - > swap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bcswap  =  bridge_find_channel ( bridge ,  bridge_channel - > swap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  bridge - > v_table - > push_peek ( bridge ,  bridge_channel ,  bcswap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Actually create the thread that will handle the channel */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! res )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  bridge_channel_impart_add ( chan ,  cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! res )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-13 22:19:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ( flags  &  AST_BRIDGE_IMPART_CHAN_MASK )  = =  AST_BRIDGE_IMPART_CHAN_INDEPENDENT )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  ast_pthread_create_detached ( & bridge_channel - > thread ,  NULL , 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												bridge_channel_ind_thread ,  bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  ast_pthread_create ( & bridge_channel - > thread ,  NULL , 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												bridge_channel_depart_thread ,  bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-08 14:56:10 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! res )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											bridge_channel_impart_wait ( cond ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-08 14:56:10 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* cleanup */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_internal_bridge_channel_set ( chan ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-31 11:14:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Lock here for ast_bridge_channel_get_chan */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_lock ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel - > chan  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-31 11:14:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_unlock ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-22 19:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_t_cleanup ( bridge_channel - > swap ,  " Bridge complete: Impart failed " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel - > swap  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_features_destroy ( bridge_channel - > features ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_channel - > features  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( bridge_channel ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_impart ( struct  ast_bridge  * bridge ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * chan , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * swap , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_features  * features , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_bridge_impart_flags  flags ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_channel_impart_cond  cond  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. done  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-06 13:23:24 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									SCOPE_TRACE ( 1 ,  " %s Bridge: %s \n " ,  ast_channel_name ( chan ) ,  bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_init ( & cond . lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_init ( & cond . cond ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  bridge_impart_internal ( bridge ,  chan ,  swap ,  features ,  flags ,  & cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Impart failed.  Signal any other waiting impart threads */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-10 05:30:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_discard_after_callback ( chan ,  AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-19 16:58:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel_impart_signal ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_destroy ( & cond . cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_destroy ( & cond . lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_depart ( struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  departable ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-06 13:23:24 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									SCOPE_TRACE ( 1 ,  " %s \n " ,  ast_channel_name ( chan ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel  =  ast_channel_internal_bridge_channel ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									departable  =  bridge_channel  & &  bridge_channel - > depart_wait ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! departable )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Channel %s cannot be departed. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Should  never  happen .   It  likely  means  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  ast_bridge_depart ( )  is  called  by  two  threads  for  the  same 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  channel ,  the  channel  was  never  imparted  to  be  departed ,  or  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  has  already  been  departed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
									
										
										
										
											2014-11-24 20:32:29 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  We  are  claiming  the  bridge_channel  reference  held  by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  bridge_channel_depart_thread ( ) . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_channel_leave_bridge ( bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  AST_CAUSE_NORMAL_CLEARING ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Wait for the depart thread to die */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Waiting for %p(%s) bridge thread to die. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_channel ,  ast_channel_name ( bridge_channel - > chan ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pthread_join ( bridge_channel - > thread ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_internal_bridge_channel_set ( chan ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* We can get rid of the bridge_channel after the depart thread has died. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( bridge_channel ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_remove ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Removing channel %s from bridge %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_name ( chan ) ,  bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Try to find the channel that we want to remove */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ( bridge_channel  =  bridge_find_channel ( bridge ,  chan ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_channel_leave_bridge ( bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  AST_CAUSE_NORMAL_CLEARING ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-16 20:48:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  kick_it ( struct  ast_bridge_channel  * bridge_channel ,  const  void  * payload ,  size_t  payload_size )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_channel_kick ( bridge_channel ,  AST_CAUSE_NORMAL_CLEARING ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-16 20:48:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_kick ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Try to find the channel that we want to kick. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ( bridge_channel  =  bridge_find_channel ( bridge ,  chan ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-21 15:51:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  ast_bridge_channel_queue_callback ( bridge_channel ,  0 ,  kick_it ,  NULL ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-16 20:48:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Point  the  bridge_channel  to  a  new  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge_channel  What  is  to  point  to  a  new  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  new_bridge  Where  the  bridge  channel  should  point . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_channel_change_bridge ( struct  ast_bridge_channel  * bridge_channel ,  struct  ast_bridge  * new_bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * old_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( new_bridge ,  + 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_channel_lock ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									old_bridge  =  bridge_channel - > bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > bridge  =  new_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_internal_bridge_set ( bridge_channel - > chan ,  new_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( bridge_channel - > chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_channel_unlock ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( old_bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_channel_moving ( struct  ast_bridge_channel  * bridge_channel ,  struct  ast_bridge  * src ,  struct  ast_bridge  * dst )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_features  * features  =  bridge_channel - > features ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_hook  * hook ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_iterator  iter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Run any moving hooks. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									iter  =  ao2_iterator_init ( features - > other_hooks ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( ;  ( hook  =  ao2_iterator_next ( & iter ) ) ;  ao2_ref ( hook ,  - 1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  remove_me ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_move_indicate_callback  move_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( hook - > type  ! =  AST_BRIDGE_HOOK_TYPE_MOVE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										move_cb  =  ( ast_bridge_move_indicate_callback )  hook - > callback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										remove_me  =  move_cb ( bridge_channel ,  hook - > hook_pvt ,  src ,  dst ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( remove_me )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " Move detection hook %p is being removed from %p(%s) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												hook ,  bridge_channel ,  ast_channel_name ( bridge_channel - > chan ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_unlink ( features - > other_hooks ,  hook ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & iter ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  bridge_do_merge ( struct  ast_bridge  * dst_bridge ,  struct  ast_bridge  * src_bridge ,  struct  ast_bridge_channel  * * kick_me ,  unsigned  int  num_kick ,  
						 
					
						
							
								
									
										
										
										
											2013-07-12 21:42:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  int  optimized ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Merging bridge %s into bridge %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_publish_merge ( dst_bridge ,  src_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Move  channels  from  src_bridge  over  to  dst_bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  We  must  use  AST_LIST_TRAVERSE_SAFE_BEGIN ( )  because 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  bridge_channel_internal_pull ( )  alters  the  list  we  are  traversing . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_BEGIN ( & src_bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge_channel - > state  ! =  BRIDGE_CHANNEL_STATE_WAIT )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  The  channel  is  already  leaving  let  it  leave  normally  because 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  pulling  it  may  delete  hooks  that  should  run  for  this  channel . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( & bridge_channel - > features - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( kick_me )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  ( idx  =  0 ;  idx  <  num_kick ;  + + idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( bridge_channel  = =  kick_me [ idx ] )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													ast_bridge_channel_leave_bridge ( bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  AST_CAUSE_NORMAL_CLEARING ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel_internal_pull ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bridge_channel - > state  ! =  BRIDGE_CHANNEL_STATE_WAIT )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  The  channel  died  as  a  result  of  being  pulled  or  it  was 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  kicked .   Leave  it  pointing  to  the  original  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel_moving ( bridge_channel ,  bridge_channel - > bridge ,  dst_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Point to new bridge.*/ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_channel_change_bridge ( bridge_channel ,  dst_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge_channel_internal_push ( bridge_channel ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-22 17:06:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_bridge_features_remove ( bridge_channel - > features , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_BRIDGE_HOOK_REMOVE_ON_PULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_bridge_channel_leave_bridge ( bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  bridge_channel - > bridge - > cause ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_END ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( kick_me )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Now  we  can  kick  any  channels  in  the  dst_bridge  without 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  potentially  dissolving  the  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( idx  =  0 ;  idx  <  num_kick ;  + + idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge_channel  =  kick_me [ idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_channel_lock ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( bridge_channel - > state  = =  BRIDGE_CHANNEL_STATE_WAIT )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_bridge_channel_leave_bridge_nolock ( bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  AST_CAUSE_NORMAL_CLEARING ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												bridge_channel_internal_pull ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_channel_unlock ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-12 21:42:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_reconfigured ( dst_bridge ,  ! optimized ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_reconfigured ( src_bridge ,  ! optimized ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Merged bridge %s into bridge %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  merge_direction  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Destination merge bridge. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * dest ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Source merge bridge. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * src ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Determine  which  bridge  should  merge  into  the  other . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge1  A  bridge  for  merging 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge2  A  bridge  for  merging 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  The  two  bridges  are  assumed  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  Which  bridge  merges  into  which  or  NULL  bridges  if  cannot  merge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  merge_direction  bridge_merge_determine_direction ( struct  ast_bridge  * bridge1 ,  struct  ast_bridge  * bridge2 )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  merge_direction  merge  =  {  NULL ,  NULL  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  bridge1_priority ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  bridge2_priority ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_test_flag ( & bridge1 - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_BRIDGE_FLAG_MERGE_INHIBIT_TO  |  AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & bridge2 - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_BRIDGE_FLAG_MERGE_INHIBIT_TO  |  AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Can  merge  either  way .   Merge  to  the  higher  priority  merge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  bridge .   Otherwise  merge  to  the  larger  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge1_priority  =  bridge1 - > v_table - > get_merge_priority ( bridge1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge2_priority  =  bridge2 - > v_table - > get_merge_priority ( bridge2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( bridge2_priority  <  bridge1_priority )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											merge . dest  =  bridge1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											merge . src  =  bridge2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( bridge1_priority  <  bridge2_priority )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											merge . dest  =  bridge2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											merge . src  =  bridge1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Merge to the larger bridge. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( bridge2 - > num_channels  < =  bridge1 - > num_channels )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												merge . dest  =  bridge1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												merge . src  =  bridge2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												merge . dest  =  bridge2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												merge . src  =  bridge1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! ast_test_flag ( & bridge1 - > feature_flags ,  AST_BRIDGE_FLAG_MERGE_INHIBIT_TO ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & bridge2 - > feature_flags ,  AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Can merge only one way. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										merge . dest  =  bridge1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										merge . src  =  bridge2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! ast_test_flag ( & bridge2 - > feature_flags ,  AST_BRIDGE_FLAG_MERGE_INHIBIT_TO ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & bridge1 - > feature_flags ,  AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Can merge only one way. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										merge . dest  =  bridge2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										merge . src  =  bridge1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  merge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Merge  two  bridges  together 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  dst_bridge  Destination  bridge  of  merge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  src_bridge  Source  bridge  of  merge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  merge_best_direction  TRUE  if  don ' t  care  about  which  bridge  merges  into  the  other . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  kick_me  Array  of  channels  to  kick  from  the  bridges . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  num_kick  Number  of  channels  in  the  kick_me  array . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  The  dst_bridge  and  src_bridge  are  assumed  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  on  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  on  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_merge_locked ( struct  ast_bridge  * dst_bridge ,  struct  ast_bridge  * src_bridge ,  int  merge_best_direction ,  struct  ast_channel  * * kick_me ,  unsigned  int  num_kick )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  merge_direction  merge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * * kick_them  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Sanity check. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( dst_bridge  & &  src_bridge  & &  dst_bridge  ! =  src_bridge  & &  ( ! num_kick  | |  kick_me ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( dst_bridge - > dissolved  | |  src_bridge - > dissolved )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't merge bridges %s and %s, at least one bridge is dissolved. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & dst_bridge - > feature_flags ,  AST_BRIDGE_FLAG_MASQUERADE_ONLY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ast_test_flag ( & src_bridge - > feature_flags ,  AST_BRIDGE_FLAG_MASQUERADE_ONLY ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't merge bridges %s and %s, masquerade only. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( dst_bridge - > inhibit_merge  | |  src_bridge - > inhibit_merge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't merge bridges %s and %s, merging temporarily inhibited. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( merge_best_direction )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										merge  =  bridge_merge_determine_direction ( dst_bridge ,  src_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										merge . dest  =  dst_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										merge . src  =  src_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! merge . dest 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ast_test_flag ( & merge . dest - > feature_flags ,  AST_BRIDGE_FLAG_MERGE_INHIBIT_TO ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ast_test_flag ( & merge . src - > feature_flags ,  AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't merge bridges %s and %s, merging inhibited. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( merge . src - > num_channels  <  2 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  For  a  two  party  bridge ,  a  channel  may  be  temporarily  removed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  from  the  source  bridge  or  the  initial  bridge  members  have  not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  joined  yet . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't merge bridge %s into bridge %s, not enough channels in source bridge. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											merge . src - > uniqueid ,  merge . dest - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( 2  +  num_kick  <  merge . dest - > num_channels  +  merge . src - > num_channels 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ! ( merge . dest - > technology - > capabilities  &  AST_BRIDGE_CAPABILITY_MULTIMIX ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ( ! ast_test_flag ( & merge . dest - > feature_flags ,  AST_BRIDGE_FLAG_SMART ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											| |  ! ( merge . dest - > allowed_capabilities  &  AST_BRIDGE_CAPABILITY_MULTIMIX ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't merge bridge %s into bridge %s, multimix is needed and it cannot be acquired. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											merge . src - > uniqueid ,  merge . dest - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( num_kick )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unsigned  int  num_to_kick  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unsigned  int  idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										kick_them  =  ast_alloca ( num_kick  *  sizeof ( * kick_them ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( idx  =  0 ;  idx  <  num_kick ;  + + idx )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											kick_them [ num_to_kick ]  =  bridge_find_channel ( merge . src ,  kick_me [ idx ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! kick_them [ num_to_kick ] )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												kick_them [ num_to_kick ]  =  bridge_find_channel ( merge . dest ,  kick_me [ idx ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( kick_them [ num_to_kick ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												+ + num_to_kick ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( num_to_kick  ! =  num_kick )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " Can't merge bridge %s into bridge %s, at least one kicked channel is not in either bridge. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												merge . src - > uniqueid ,  merge . dest - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_do_merge ( merge . dest ,  merge . src ,  kick_them ,  num_kick ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_merge ( struct  ast_bridge  * dst_bridge ,  struct  ast_bridge  * src_bridge ,  int  merge_best_direction ,  struct  ast_channel  * * kick_me ,  unsigned  int  num_kick )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Sanity check. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( dst_bridge  & &  src_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock_both ( dst_bridge ,  src_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  bridge_merge_locked ( dst_bridge ,  src_bridge ,  merge_best_direction ,  kick_me ,  num_kick ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( src_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( dst_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  bridge_do_move ( struct  ast_bridge  * dst_bridge ,  struct  ast_bridge_channel  * bridge_channel ,  int  attempt_recovery ,  
						 
					
						
							
								
									
										
										
										
											2013-07-12 21:42:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  int  optimized ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * orig_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  was_in_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge_channel - > swap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Moving %p(%s) into bridge %s swapping with %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge_channel ,  ast_channel_name ( bridge_channel - > chan ) ,  dst_bridge - > uniqueid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( bridge_channel - > swap ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Moving %p(%s) into bridge %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge_channel ,  ast_channel_name ( bridge_channel - > chan ) ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									orig_bridge  =  bridge_channel - > bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									was_in_bridge  =  bridge_channel - > in_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel_internal_pull ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge_channel - > state  ! =  BRIDGE_CHANNEL_STATE_WAIT )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  The  channel  died  as  a  result  of  being  pulled .   Leave  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  pointing  to  the  original  bridge . 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-22 19:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Clear  out  the  swap  channel  pointer .   A  ref  is  not  held 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  by  bridge_channel - > swap  at  this  point . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-22 19:30:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel - > swap  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-12 21:42:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_reconfigured ( orig_bridge ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Point to new bridge.*/ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( orig_bridge ,  + 1 ) ; /* Keep a ref in case the push fails. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel_change_bridge ( bridge_channel ,  dst_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel_moving ( bridge_channel ,  orig_bridge ,  dst_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-02-19 19:06:14 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge_channel_internal_push_full ( bridge_channel ,  optimized ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Try to put the channel back into the original bridge. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-22 17:06:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_features_remove ( bridge_channel - > features , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_BRIDGE_HOOK_REMOVE_ON_PULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( attempt_recovery  & &  was_in_bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Point back to original bridge. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge_channel_change_bridge ( bridge_channel ,  orig_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( bridge_channel_internal_push ( bridge_channel ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-22 17:06:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_bridge_features_remove ( bridge_channel - > features , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													AST_BRIDGE_HOOK_REMOVE_ON_PULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_bridge_channel_leave_bridge ( bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  bridge_channel - > bridge - > cause ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_bridge_channel_leave_bridge ( bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  bridge_channel - > bridge - > cause ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-23 18:33:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											bridge_channel_settle_owed_events ( orig_bridge ,  bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-19 19:06:14 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! optimized )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-23 18:33:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel_settle_owed_events ( orig_bridge ,  bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-12 21:42:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_reconfigured ( dst_bridge ,  ! optimized ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_reconfigured ( orig_bridge ,  ! optimized ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_ref ( orig_bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Move  a  channel  from  one  bridge  to  another . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  dst_bridge  Destination  bridge  of  bridge  channel  move . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  src_bridge  Source  bridge  of  bridge  channel  move . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan  Channel  to  move . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  swap  Channel  to  replace  in  dst_bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  attempt_recovery  TRUE  if  failure  attempts  to  push  channel  back  into  original  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  The  dst_bridge  and  src_bridge  are  assumed  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  on  success . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  on  failure . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_move_locked ( struct  ast_bridge  * dst_bridge ,  struct  ast_bridge  * src_bridge ,  struct  ast_channel  * chan ,  struct  ast_channel  * swap ,  int  attempt_recovery )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( dst_bridge - > dissolved  | |  src_bridge - > dissolved )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't move channel %s from bridge %s into bridge %s, at least one bridge is dissolved. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ,  src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & dst_bridge - > feature_flags ,  AST_BRIDGE_FLAG_MASQUERADE_ONLY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ast_test_flag ( & src_bridge - > feature_flags ,  AST_BRIDGE_FLAG_MASQUERADE_ONLY ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't move channel %s from bridge %s into bridge %s, masquerade only. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ,  src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( dst_bridge - > inhibit_merge  | |  src_bridge - > inhibit_merge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't move channel %s from bridge %s into bridge %s, temporarily inhibited. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ,  src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel  =  bridge_find_channel ( src_bridge ,  chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge_channel )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't move channel %s from bridge %s into bridge %s, channel not in bridge. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ,  src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge_channel - > state  ! =  BRIDGE_CHANNEL_STATE_WAIT )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't move channel %s from bridge %s into bridge %s, channel leaving bridge. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ,  src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & bridge_channel - > features - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Can't move channel %s from bridge %s into bridge %s, channel immovable. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ,  src_bridge - > uniqueid ,  dst_bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( swap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_channel  * bridge_channel_swap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel_swap  =  bridge_find_channel ( dst_bridge ,  swap ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! bridge_channel_swap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " Can't move channel %s from bridge %s into bridge %s, swap channel %s not in bridge. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_name ( chan ) ,  src_bridge - > uniqueid ,  dst_bridge - > uniqueid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_name ( swap ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge_channel_swap - > state  ! =  BRIDGE_CHANNEL_STATE_WAIT )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " Can't move channel %s from bridge %s into bridge %s, swap channel %s leaving bridge. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_name ( chan ) ,  src_bridge - > uniqueid ,  dst_bridge - > uniqueid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_name ( swap ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_channel - > swap  =  swap ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  bridge_do_move ( dst_bridge ,  bridge_channel ,  attempt_recovery ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_move ( struct  ast_bridge  * dst_bridge ,  struct  ast_bridge  * src_bridge ,  struct  ast_channel  * chan ,  struct  ast_channel  * swap ,  int  attempt_recovery )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock_both ( dst_bridge ,  src_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  bridge_move_locked ( dst_bridge ,  src_bridge ,  chan ,  swap ,  attempt_recovery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( src_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( dst_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_add_channel ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan ,  
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_features  * features ,  int  play_tone ,  const  char  * xfersound ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_bridge  * ,  chan_bridge ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_channel  * ,  yanked_chan ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-16 14:51:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_moh_stop ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chan_bridge  =  ast_channel_get_bridge ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( chan_bridge )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-04-13 13:50:04 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* The channel is in a bridge so it is not getting any new features. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_features_destroy ( features ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_lock_both ( bridge ,  chan_bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_channel  =  bridge_find_channel ( chan_bridge ,  chan ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge_move_locked ( bridge ,  chan_bridge ,  chan ,  NULL ,  1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_unlock ( chan_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  bridge_move_locked ( )  will  implicitly  ensure  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  bridge_channel  is  not  NULL . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( bridge_channel  ! =  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Additional  checks  if  the  channel  we  just  stole  dissolves  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  original  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_dissolve_check_stolen ( chan_bridge ,  bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_unlock ( chan_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Slightly less easy case. We need to yank channel A from
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  where  he  currently  is  and  impart  him  into  our  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										yanked_chan  =  ast_channel_yank ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! yanked_chan )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " Could not gain control of channel %s \n " ,  ast_channel_name ( chan ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-13 13:50:04 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_bridge_features_destroy ( features ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ast_channel_state ( yanked_chan )  ! =  AST_STATE_UP )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_answer ( yanked_chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_channel_ref ( yanked_chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-13 22:19:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ast_bridge_impart ( bridge ,  yanked_chan ,  NULL ,  features , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_BRIDGE_IMPART_CHAN_INDEPENDENT ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* It is possible for us to yank a channel and have some other
 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-01 00:49:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 *  thread  start  a  PBX  on  the  channel  after  we  yanked  it .  In  particular , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix two race conditions and ref counting issue when joining a bridge
These problems were all caught by a test in the Asterisk Test Suite that
originated some Local channels and attempted to move the ;2 half of the Local
channel into a bridge using the Bridge AMI action.
(1) When originating a channel, the Newchannel event is emitted quickly;
    however, the ;2 channel will not have a pbx thread assigned to it until
    after the outbound 'dialing' for the ;1 is complete. Thus, there is a period
    of time where the outside world "knows" of the channel's existence and can
    influence it but Asterisk has not yet started the dialplan execution thread.
    If a Bridge AMI action is taken on the channel, the channel appears to be a
    Dialed channel with no PBX thread; hence, the channel will be imparted into
    the Bridge by first 'yanking' the channel. At the same time, a race condition
    can occur after the yank (but before entering the bridge) when ;1 answers
    and starts a PBX on the ;2. The end result currently is an assertion failure
    in the Bridging API, as a channel with a PBX is imparted into the Bridge.
    There's no way to prevent AMI from attempting to Bridge a channel
    immediately after creation; likewise, holding the channel lock through the
    entire Dial operation is unwise (and impossible). Instead of treating the
    presence of a PBX thread as an error, we simply bail out of the adding the
    channel to the bridge through ast_bridge_impart. The Bridge action will
    then fail - but we avoid a situation where the channel is both executing
    a PBX thread and simultaneously being given a separate thread in the
    bridging system (which would be a "bad thing"). Since imparting a channel
    with a PBX *can* occur and is not a programming error, the asserts have been
    removed.
(2) When the first condition occurs, we have to take one of two actions: either
    hangup the yanked channel as it did not enter the bridge, or deref it
    because we don't own it. We can determine if we own it or not by testing
    for the presence of the PBX thread. If we hung it up directly, we'd crash.
(3) bridge_find_channel does not increase the reference count of the
    ast_bridge_channel object. The RAII_VAR usage in ast_bridge_add_channel
    thus created a ticking time bomb in whatever bridge the channel moved into,
    as the destructor for the ast_bridge_channel object would be called.
Review: https://reviewboard.asterisk.org/r/2741/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-08-12 15:59:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 *  this  can  theoretically  happen  on  the  ; 2  of  a  Local  channel  if  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  yank  it  prior  to  the  ; 1  being  answered .  Make  sure  that  it  isn ' t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  executing  a  PBX  before  hanging  it  up . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ast_channel_pbx ( yanked_chan ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_unref ( yanked_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_hangup ( yanked_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( play_tone  & &  ! ast_strlen_zero ( xfersound ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_channel  * play_chan  =  yanked_chan  ? :  chan ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										RAII_VAR ( struct  ast_bridge_channel  * ,  play_bridge_channel ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_lock ( play_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										play_bridge_channel  =  ast_channel_get_bridge_channel ( play_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( play_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! play_bridge_channel )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-26 14:38:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " Unable to play tone for channel %s. No longer in a bridge. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_name ( play_chan ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-25 22:28:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_channel_queue_playfile ( play_bridge_channel ,  NULL ,  xfersound ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  bridge_allows_optimization ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ! ( bridge - > inhibit_merge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  bridge - > dissolved 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ast_test_flag ( & bridge - > feature_flags ,  AST_BRIDGE_FLAG_MASQUERADE_ONLY ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Lock  the  unreal  channel  stack  for  chan  and  prequalify  it . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan  Unreal  channel  writing  a  frame  into  the  channel  driver . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  It  is  assumed  that  chan  is  already  locked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-19 16:47:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ return  bridge  on  success  with  bridge  and  bridge_channel  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ retval  NULL  if  cannot  do  optimization  now . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_bridge  * optimize_lock_chan_stack ( struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! AST_LIST_EMPTY ( ast_channel_readq ( chan ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-08 12:38:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( ast_channel_flags ( chan ) ,  AST_FLAG_EMULATE_DTMF ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-19 22:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_channel_has_audio_frame_or_monitor ( chan ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-19 17:55:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Channel has an active monitor, audiohook, or framehook. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel  =  ast_channel_internal_bridge_channel ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridge_channel  | |  ast_bridge_channel_trylock ( bridge_channel ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge  =  bridge_channel - > bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge_channel - > activity  ! =  BRIDGE_CHANNEL_THREAD_SIMPLE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  bridge_channel - > state  ! =  BRIDGE_CHANNEL_STATE_WAIT 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										| |  ast_bridge_trylock ( bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_channel_unlock ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge_channel_internal_allows_optimization ( bridge_channel )  | | 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											! bridge_allows_optimization ( bridge ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_channel_unlock ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Lock  the  unreal  channel  stack  for  peer  and  prequalify  it . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  peer  Other  unreal  channel  in  the  pair . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-19 16:47:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ return  bridge  on  success  with  bridge ,  bridge_channel ,  and  peer  locked . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ retval  NULL  if  cannot  do  optimization  now . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_bridge  * optimize_lock_peer_stack ( struct  ast_channel  * peer )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_channel_trylock ( peer ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! AST_LIST_EMPTY ( ast_channel_readq ( peer ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-08 12:38:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( ast_channel_flags ( peer ) ,  AST_FLAG_EMULATE_DTMF ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-19 22:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_channel_has_audio_frame_or_monitor ( peer ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-19 17:55:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Peer has an active monitor, audiohook, or framehook. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel  =  ast_channel_internal_bridge_channel ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridge_channel  | |  ast_bridge_channel_trylock ( bridge_channel ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge  =  bridge_channel - > bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge_channel - > activity  ! =  BRIDGE_CHANNEL_THREAD_IDLE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  bridge_channel - > state  ! =  BRIDGE_CHANNEL_STATE_WAIT 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										| |  ast_bridge_trylock ( bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_channel_unlock ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge_allows_optimization ( bridge )  | | 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											! bridge_channel_internal_allows_optimization ( bridge_channel ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_channel_unlock ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Indicates  allowability  of  a  swap  optimization 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								enum  bridge_allow_swap  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Bridges cannot allow for a swap optimization to occur */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SWAP_PROHIBITED , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Bridge swap optimization can occur into the chan_bridge */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SWAP_TO_CHAN_BRIDGE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Bridge swap optimization can occur into the peer_bridge */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SWAP_TO_PEER_BRIDGE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Determine  if  two  bridges  allow  for  swap  optimization  to  occur 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  chan_bridge  First  bridge  being  tested 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  peer_bridge  Second  bridge  being  tested 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  Allowability  of  swap  optimization 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  bridge_allow_swap  bridges_allow_swap_optimization ( struct  ast_bridge  * chan_bridge ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge  * peer_bridge ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  chan_priority ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  peer_priority ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_test_flag ( & chan_bridge - > feature_flags , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_BRIDGE_FLAG_SWAP_INHIBIT_TO  |  AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM  | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & peer_bridge - > feature_flags , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_BRIDGE_FLAG_SWAP_INHIBIT_TO  |  AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM  | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Can  swap  either  way .   Swap  to  the  higher  priority  merge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chan_priority  =  chan_bridge - > v_table - > get_merge_priority ( chan_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer_priority  =  peer_bridge - > v_table - > get_merge_priority ( peer_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( chan_bridge - > num_channels  = =  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  chan_priority  < =  peer_priority )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  SWAP_TO_PEER_BRIDGE ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( peer_bridge - > num_channels  = =  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  peer_priority  < =  chan_priority )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  SWAP_TO_CHAN_BRIDGE ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( chan_bridge - > num_channels  = =  2 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & chan_bridge - > feature_flags ,  AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM  |  AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & peer_bridge - > feature_flags ,  AST_BRIDGE_FLAG_SWAP_INHIBIT_TO ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Can swap optimize only one way. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  SWAP_TO_PEER_BRIDGE ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( peer_bridge - > num_channels  = =  2 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & peer_bridge - > feature_flags ,  AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM  |  AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & chan_bridge - > feature_flags ,  AST_BRIDGE_FLAG_SWAP_INHIBIT_TO ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Can swap optimize only one way. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  SWAP_TO_CHAN_BRIDGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  SWAP_PROHIBITED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Check  and  attempt  to  swap  optimize  out  the  unreal  channels . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan_bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan_bridge_channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  peer_bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  peer_bridge_channel 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  pvt  Unreal  data  containing  callbacks  to  call  if  the  optimization  actually 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  happens 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  1  if  unreal  channels  failed  to  optimize  out . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  if  unreal  channels  were  not  optimized  out . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  if  unreal  channels  were  optimized  out . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  try_swap_optimize_out ( struct  ast_bridge  * chan_bridge ,  
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * chan_bridge_channel ,  struct  ast_bridge  * peer_bridge , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * peer_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_unreal_pvt  * pvt ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * dst_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * dst_bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * src_bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * other ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( bridges_allow_swap_optimization ( chan_bridge ,  peer_bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  SWAP_TO_CHAN_BRIDGE : 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										dst_bridge  =  chan_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dst_bridge_channel  =  chan_bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										src_bridge_channel  =  peer_bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  SWAP_TO_PEER_BRIDGE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dst_bridge  =  peer_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dst_bridge_channel  =  peer_bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										src_bridge_channel  =  chan_bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  SWAP_PROHIBITED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									other  =  ast_bridge_channel_peer ( src_bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( other  & &  other - > state  = =  BRIDGE_CHANNEL_STATE_WAIT )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-18 20:33:37 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										unsigned  int  id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_channel_trylock ( other - > chan ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										id  =  ast_atomic_fetchadd_int ( ( int  * )  & optimization_id ,  + 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 18:52:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-05-28 22:54:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_verb ( 4 ,  " Move-swap optimizing %s <-- %s. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_channel_name ( dst_bridge_channel - > chan ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( other - > chan ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( pvt  & &  ! ast_test_flag ( pvt ,  AST_UNREAL_OPTIMIZE_BEGUN )  & &  pvt - > callbacks 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												& &  pvt - > callbacks - > optimization_started )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 18:52:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											pvt - > callbacks - > optimization_started ( pvt ,  other - > chan , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													dst_bridge_channel - > chan  = =  pvt - > owner  ?  AST_UNREAL_OWNER  :  AST_UNREAL_CHAN , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_set_flag ( pvt ,  AST_UNREAL_OPTIMIZE_BEGUN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										other - > swap  =  dst_bridge_channel - > chan ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! bridge_do_move ( dst_bridge ,  other ,  1 ,  1 ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_bridge_channel_leave_bridge ( src_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  AST_CAUSE_NORMAL_CLEARING ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 18:52:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( pvt  & &  pvt - > callbacks  & &  pvt - > callbacks - > optimization_finished )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pvt - > callbacks - > optimization_finished ( pvt ,  res  = =  1 ,  id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-18 20:33:37 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_channel_unlock ( other - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Indicates  allowability  of  a  merge  optimization 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								enum  bridge_allow_merge  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Bridge properties prohibit merge optimization */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MERGE_PROHIBITED , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Merge optimization cannot occur because the source bridge has too few channels */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MERGE_NOT_ENOUGH_CHANNELS , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Merge optimization cannot occur because multimix capability could not be requested */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MERGE_NO_MULTIMIX , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! Merge optimization allowed between bridges */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MERGE_ALLOWED , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Determines  allowability  of  a  merge  optimization 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  The  merge  output  parameter  is  undefined  if  MERGE_PROHIBITED  is  returned .  For  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  and  other  failure  returns ,  a  merge  direction  was  determined ,  and  the  parameter  is  safe  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  access . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan_bridge  First  bridge  being  tested 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  peer_bridge  Second  bridge  being  tested 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  num_kick_channels  The  number  of  channels  to  remove  from  the  bridges  during  merging 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param [ out ]  merge  Indicates  the  recommended  direction  for  the  bridge  merge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  enum  bridge_allow_merge  bridges_allow_merge_optimization ( struct  ast_bridge  * chan_bridge ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge  * peer_bridge ,  int  num_kick_channels ,  struct  merge_direction  * merge ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* merge  =  bridge_merge_determine_direction ( chan_bridge ,  peer_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! merge - > dest )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  MERGE_PROHIBITED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( merge - > src - > num_channels  <  2 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  MERGE_NOT_ENOUGH_CHANNELS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ( 2  +  num_kick_channels )  <  merge - > dest - > num_channels  +  merge - > src - > num_channels 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ! ( merge - > dest - > technology - > capabilities  &  AST_BRIDGE_CAPABILITY_MULTIMIX ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ( ! ast_test_flag ( & merge - > dest - > feature_flags ,  AST_BRIDGE_FLAG_SMART ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											| |  ! ( merge - > dest - > allowed_capabilities  &  AST_BRIDGE_CAPABILITY_MULTIMIX ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  MERGE_NO_MULTIMIX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  MERGE_ALLOWED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Check  and  attempt  to  merge  optimize  out  the  unreal  channels . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan_bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan_bridge_channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  peer_bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  peer_bridge_channel 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  pvt  Unreal  data  containing  callbacks  to  call  if  the  optimization  actually 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  happens 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  if  unreal  channels  were  not  optimized  out . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  if  unreal  channels  were  optimized  out . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  try_merge_optimize_out ( struct  ast_bridge  * chan_bridge ,  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * chan_bridge_channel ,  struct  ast_bridge  * peer_bridge , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * peer_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_unreal_pvt  * pvt ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  merge_direction  merge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * kick_me [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chan_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 18:52:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  int  id ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( bridges_allow_merge_optimization ( chan_bridge ,  peer_bridge ,  ARRAY_LEN ( kick_me ) ,  & merge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  MERGE_ALLOWED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  MERGE_PROHIBITED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  MERGE_NOT_ENOUGH_CHANNELS : 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 4 ,  " Can't optimize %s -- %s out, not enough channels in bridge %s. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan_bridge_channel - > chan ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( peer_bridge_channel - > chan ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											merge . src - > uniqueid ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  MERGE_NO_MULTIMIX : 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 4 ,  " Can't optimize %s -- %s out, multimix is needed and it cannot be acquired. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan_bridge_channel - > chan ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( peer_bridge_channel - > chan ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-05-28 22:54:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_verb ( 4 ,  " Merge optimizing %s -- %s out. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_channel_name ( chan_bridge_channel - > chan ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_name ( peer_bridge_channel - > chan ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 18:52:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									id  =  ast_atomic_fetchadd_int ( ( int  * )  & optimization_id ,  + 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( pvt  & &  ! ast_test_flag ( pvt ,  AST_UNREAL_OPTIMIZE_BEGUN )  & &  pvt - > callbacks 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  pvt - > callbacks - > optimization_started )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 18:52:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pvt - > callbacks - > optimization_started ( pvt ,  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												merge . dest  = =  ast_channel_internal_bridge ( pvt - > owner )  ?  AST_UNREAL_OWNER  :  AST_UNREAL_CHAN , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_set_flag ( pvt ,  AST_UNREAL_OPTIMIZE_BEGUN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_do_merge ( merge . dest ,  merge . src ,  kick_me ,  ARRAY_LEN ( kick_me ) ,  1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( pvt  & &  pvt - > callbacks  & &  pvt - > callbacks - > optimization_finished )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 18:52:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pvt - > callbacks - > optimization_finished ( pvt ,  1 ,  id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_unreal_optimize_out ( struct  ast_channel  * chan ,  struct  ast_channel  * peer ,  struct  ast_unreal_pvt  * pvt )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * chan_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * peer_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * chan_bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * peer_bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chan_bridge  =  optimize_lock_chan_stack ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! chan_bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chan_bridge_channel  =  ast_channel_internal_bridge_channel ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									peer_bridge  =  optimize_lock_peer_stack ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( peer_bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										peer_bridge_channel  =  ast_channel_internal_bridge_channel ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  try_swap_optimize_out ( chan_bridge ,  chan_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer_bridge ,  peer_bridge_channel ,  pvt ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! res )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 14:26:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  try_merge_optimize_out ( chan_bridge ,  chan_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer_bridge ,  peer_bridge_channel ,  pvt ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( 0  <  res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Release peer locks. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_unlock ( peer_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_channel_unlock ( peer_bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Release chan locks. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( chan_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_channel_unlock ( chan_bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								enum  ast_bridge_optimization  ast_bridges_allow_optimization ( struct  ast_bridge  * chan_bridge ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge  * peer_bridge ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  merge_direction  merge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridge_allows_optimization ( chan_bridge )  | |  ! bridge_allows_optimization ( peer_bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_OPTIMIZE_PROHIBITED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( bridges_allow_swap_optimization ( chan_bridge ,  peer_bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  SWAP_TO_CHAN_BRIDGE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_OPTIMIZE_SWAP_TO_CHAN_BRIDGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  SWAP_TO_PEER_BRIDGE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_OPTIMIZE_SWAP_TO_PEER_BRIDGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  SWAP_PROHIBITED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Two channels will be kicked from the bridges, the unreal;1 and unreal;2 channels */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridges_allow_merge_optimization ( chan_bridge ,  peer_bridge ,  2 ,  & merge )  ! =  MERGE_ALLOWED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_OPTIMIZE_PROHIBITED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( merge . dest  = =  chan_bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_OPTIMIZE_MERGE_TO_CHAN_BRIDGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_OPTIMIZE_MERGE_TO_PEER_BRIDGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  bridge_merge_inhibit_nolock ( struct  ast_bridge  * bridge ,  int  request )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  new_request ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									new_request  =  bridge - > inhibit_merge  +  request ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( 0  < =  new_request ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > inhibit_merge  =  new_request ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_merge_inhibit ( struct  ast_bridge  * bridge ,  int  request )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_merge_inhibit_nolock ( bridge ,  request ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_suspend ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-30 21:04:30 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* XXX ASTERISK-21271 the case of a dissolved bridge while channel is suspended is not handled. */  
						 
					
						
							
								
									
										
										
										
											2013-08-15 18:20:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* XXX ASTERISK-21271 suspend/unsuspend needs to be rethought. The caller must block until it has successfully suspended the channel for temporary control. */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* XXX ASTERISK-21271 external suspend/unsuspend needs to be eliminated. The channel may be playing a file at the time and stealing it then is not good. */  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ( bridge_channel  =  bridge_find_channel ( bridge ,  chan ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel_internal_suspend_nolock ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_unsuspend ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-30 21:04:30 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* XXX ASTERISK-21271 the case of a dissolved bridge while channel is suspended is not handled. */  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ( bridge_channel  =  bridge_find_channel ( bridge ,  chan ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel_internal_unsuspend_nolock ( bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_technology_suspend ( struct  ast_bridge_technology  * technology )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									technology - > suspended  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_technology_unsuspend ( struct  ast_bridge_technology  * technology )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-08-15 17:57:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  XXX  We  may  want  the  act  of  unsuspending  a  bridge  technology 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  to  prod  all  existing  bridges  to  see  if  they  should  start 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  using  it . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									technology - > suspended  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_features_register ( enum  ast_bridge_builtin_feature  feature ,  ast_bridge_hook_callback  callback ,  const  char  * dtmf )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ARRAY_LEN ( builtin_features_handlers )  < =  feature 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  builtin_features_handlers [ feature ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_strlen_zero ( dtmf ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( builtin_features_dtmf [ feature ] ,  dtmf ,  sizeof ( builtin_features_dtmf [ feature ] ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									builtin_features_handlers [ feature ]  =  callback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_features_unregister ( enum  ast_bridge_builtin_feature  feature )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ARRAY_LEN ( builtin_features_handlers )  < =  feature 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! builtin_features_handlers [ feature ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									builtin_features_handlers [ feature ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 21:34:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_features_do ( enum  ast_bridge_builtin_feature  feature ,  struct  ast_bridge_channel  * bridge_channel ,  void  * hook_pvt )  
						 
					
						
							
								
									
										
										
										
											2013-07-05 14:54:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_callback  callback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ARRAY_LEN ( builtin_features_handlers )  < =  feature )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									callback  =  builtin_features_handlers [ feature ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! callback )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 21:34:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									callback ( bridge_channel ,  hook_pvt ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-05 14:54:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_interval_register ( enum  ast_bridge_builtin_interval  interval ,  ast_bridge_builtin_set_limits_fn  callback )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ARRAY_LEN ( builtin_interval_handlers )  < =  interval 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  builtin_interval_handlers [ interval ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									builtin_interval_handlers [ interval ]  =  callback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_interval_unregister ( enum  ast_bridge_builtin_interval  interval )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ARRAY_LEN ( builtin_interval_handlers )  < =  interval 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! builtin_interval_handlers [ interval ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									builtin_interval_handlers [ interval ]  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Bridge  hook  destructor . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  vhook  Object  to  destroy . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_hook_destroy ( void  * vhook )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_hook  * hook  =  vhook ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( hook - > destructor )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hook - > destructor ( hook - > hook_pvt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Allocate  and  setup  a  generic  bridge  hook . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  size  How  big  an  object  to  allocate . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  callback  Function  to  execute  upon  activation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  hook_pvt  Unique  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  destructor  Optional  destructor  callback  for  hook_pvt  data 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  remove_flags  Dictates  what  situations  the  hook  should  be  removed . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-19 16:47:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ return  hook  on  success . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ retval  NULL  on  error . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_bridge_hook  * bridge_hook_generic ( size_t  size ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_callback  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * hook_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_hook  * hook ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Allocate new hook and setup it's basic variables */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hook  =  ao2_alloc_options ( size ,  bridge_hook_destroy ,  AO2_ALLOC_OPT_LOCK_NOLOCK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( hook )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hook - > callback  =  callback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hook - > destructor  =  destructor ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hook - > hook_pvt  =  hook_pvt ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_set_flag ( & hook - > remove_flags ,  remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  hook ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_dtmf_hook ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * dtmf , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_callback  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * hook_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_hook_dtmf  * hook ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Allocate new hook and setup it's various variables */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hook  =  ( struct  ast_bridge_hook_dtmf  * )  bridge_hook_generic ( sizeof ( * hook ) ,  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hook_pvt ,  destructor ,  remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! hook )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hook - > generic . type  =  AST_BRIDGE_HOOK_TYPE_DTMF ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_copy_string ( hook - > dtmf . code ,  dtmf ,  sizeof ( hook - > dtmf . code ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Once done we put it in the container. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  ao2_link ( features - > dtmf_hooks ,  hook )  ?  0  :  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-20 17:21:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Could  not  link  the  hook  into  the  container . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Remove  the  hook_pvt  destructor  call  from  the  hook  since  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  are  returning  failure  to  install  the  hook . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hook - > generic . destructor  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-20 17:21:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_ref ( hook ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Attach  an  other  hook  to  a  bridge  features  structure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  features  Bridge  features  structure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  callback  Function  to  execute  upon  activation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  hook_pvt  Unique  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  destructor  Optional  destructor  callback  for  hook_pvt  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  remove_flags  Dictates  what  situations  the  hook  should  be  removed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  type  What  type  of  hook  is  being  attached . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  on  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  - 1  on  failure  ( The  caller  must  cleanup  any  hook_pvt  resources . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_other_hook ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_hook_callback  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * hook_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_bridge_hook_type  type ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_hook  * hook ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Allocate new hook and setup it's various variables */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hook  =  bridge_hook_generic ( sizeof ( * hook ) ,  callback ,  hook_pvt ,  destructor , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! hook )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hook - > type  =  type ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Once done we put it in the container. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  ao2_link ( features - > other_hooks ,  hook )  ?  0  :  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-20 17:21:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Could  not  link  the  hook  into  the  container . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Remove  the  hook_pvt  destructor  call  from  the  hook  since  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  are  returning  failure  to  install  the  hook . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hook - > destructor  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_ref ( hook ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_hangup_hook ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_hook_callback  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * hook_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  bridge_other_hook ( features ,  callback ,  hook_pvt ,  destructor ,  remove_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_BRIDGE_HOOK_TYPE_HANGUP ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_join_hook ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_callback  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * hook_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bridge_other_hook ( features ,  callback ,  hook_pvt ,  destructor ,  remove_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_BRIDGE_HOOK_TYPE_JOIN ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_leave_hook ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_callback  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * hook_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  bridge_other_hook ( features ,  callback ,  hook_pvt ,  destructor ,  remove_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_BRIDGE_HOOK_TYPE_LEAVE ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_talk_detector_hook ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_talking_indicate_callback  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * hook_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_hook_callback  hook_cb  =  ( ast_bridge_hook_callback )  callback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bridge_other_hook ( features ,  hook_cb ,  hook_pvt ,  destructor ,  remove_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_BRIDGE_HOOK_TYPE_TALK ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_move_hook ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_move_indicate_callback  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * hook_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_callback  hook_cb  =  ( ast_bridge_hook_callback )  callback ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bridge_other_hook ( features ,  hook_cb ,  hook_pvt ,  destructor ,  remove_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_BRIDGE_HOOK_TYPE_MOVE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_interval_hook ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
									
										
										
										
											2013-08-21 15:51:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_hook_timer_option  flags , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  int  interval , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_callback  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * hook_pvt , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_hook_timer  * hook ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! features  | | ! interval  | |  ! callback )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Allocate new hook and setup it's various variables */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hook  =  ( struct  ast_bridge_hook_timer  * )  bridge_hook_generic ( sizeof ( * hook ) ,  callback , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hook_pvt ,  destructor ,  remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! hook )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hook - > generic . type  =  AST_BRIDGE_HOOK_TYPE_TIMER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									hook - > timer . interval  =  interval ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-21 15:51:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hook - > timer . trip_time  =  ast_tvadd ( ast_tvnow ( ) ,  ast_samp2tv ( interval ,  1000 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hook - > timer . seqno  =  ast_atomic_fetchadd_int ( ( int  * )  & features - > interval_sequence ,  + 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-21 15:51:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hook - > timer . flags  =  flags ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Putting interval hook %p with interval %u in the heap on features %p \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hook ,  hook - > timer . interval ,  features ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_heap_wrlock ( features - > interval_hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									res  =  ast_heap_push ( features - > interval_hooks ,  hook ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-20 17:21:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_heap_unlock ( features - > interval_hooks ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-20 17:21:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Could  not  push  the  hook  into  the  heap 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Remove  the  hook_pvt  destructor  call  from  the  hook  since  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  are  returning  failure  to  install  the  hook . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hook - > generic . destructor  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_ref ( hook ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res  ?  - 1  :  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_features_enable ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_bridge_builtin_feature  feature , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * dtmf , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  * config , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_hook_pvt_destructor  destructor , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ARRAY_LEN ( builtin_features_handlers )  < =  feature 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! builtin_features_handlers [ feature ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If no alternate DTMF stream was provided use the default one */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( dtmf ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dtmf  =  builtin_features_dtmf [ feature ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If no DTMF is still available (ie: it has been disabled) then error out now */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_strlen_zero ( dtmf ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " Failed to enable built in feature %u on %p, no DTMF string is available for it. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												feature ,  features ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  The  rest  is  basically  pretty  easy .   We  create  another  hook 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  using  the  built  in  feature ' s  DTMF  callback .   Easy  as  pie . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ast_bridge_dtmf_hook ( features ,  dtmf ,  builtin_features_handlers [ feature ] , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										config ,  destructor ,  remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_features_limits_construct ( struct  ast_bridge_features_limits  * limits )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memset ( limits ,  0 ,  sizeof ( * limits ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_string_field_init ( limits ,  256 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_features_limits_destroy ( struct  ast_bridge_features_limits  * limits )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_free_memory ( limits ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_features_set_limits ( struct  ast_bridge_features  * features ,  
						 
					
						
							
								
									
										
										
										
											2013-07-26 21:10:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_features_limits  * limits , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  remove_flags ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( builtin_interval_handlers [ AST_BRIDGE_BUILTIN_INTERVAL_LIMITS ] )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 21:10:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_builtin_set_limits_fn  callback ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 21:10:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										callback  =  builtin_interval_handlers [ AST_BRIDGE_BUILTIN_INTERVAL_LIMITS ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  callback ( features ,  limits ,  remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_log ( LOG_ERROR ,  " Attempted to set limits without an AST_BRIDGE_BUILTIN_INTERVAL_LIMITS callback registered. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_features_set_flag ( struct  ast_bridge_features  * features ,  unsigned  int  flag )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_set_flag ( & features - > feature_flags ,  flag ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									features - > usable  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  ao2  object  match  hooks  with  appropriate  remove_flags . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  Feature  hook  object . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 18:07:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  arg  Removal  flags 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  flags  Not  used 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 18:07:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ retval  CMP_MATCH  if  hook ' s  remove_flags  match  the  removal  flags  set . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ retval  0  if  not  match . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  hook_remove_match ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_hook  * hook  =  obj ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_bridge_hook_remove_flags  * remove_flags  =  arg ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & hook - > remove_flags ,  * remove_flags ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  CMP_MATCH ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Remove  all  hooks  with  appropriate  remove_flags  in  the  container . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  hooks  Hooks  container  to  work  on . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  remove_flags  Determinator  for  whether  hook  is  removed 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  hooks_remove_container ( struct  ao2_container  * hooks ,  enum  ast_bridge_hook_remove_flags  remove_flags )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( hooks ,  OBJ_UNLINK  |  OBJ_NODATA  |  OBJ_MULTIPLE , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hook_remove_match ,  & remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-05 19:19:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Remove  all  hooks  in  the  heap  with  appropriate  remove_flags  set . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  hooks  Hooks  heap  to  work  on . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  remove_flags  Determinator  for  whether  hook  is  removed 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  hooks_remove_heap ( struct  ast_heap  * hooks ,  enum  ast_bridge_hook_remove_flags  remove_flags )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_hook  * hook ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  changed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_heap_wrlock ( hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									do  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										changed  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( idx  =  ast_heap_size ( hooks ) ;  idx ;  - - idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											hook  =  ast_heap_peek ( hooks ,  idx ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ast_test_flag ( & hook - > remove_flags ,  remove_flags ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_heap_remove ( hooks ,  hook ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ao2_ref ( hook ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												changed  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  while  ( changed ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_heap_unlock ( hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 15:28:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_features_remove ( struct  ast_bridge_features  * features ,  enum  ast_bridge_hook_remove_flags  remove_flags )  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hooks_remove_container ( features - > dtmf_hooks ,  remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hooks_remove_container ( features - > other_hooks ,  remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 20:47:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hooks_remove_heap ( features - > interval_hooks ,  remove_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  interval_hook_time_cmp ( void  * a ,  void  * b )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_hook_timer  * hook_a  =  a ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_hook_timer  * hook_b  =  b ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  cmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cmp  =  ast_tvcmp ( hook_b - > timer . trip_time ,  hook_a - > timer . trip_time ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cmp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  cmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cmp  =  hook_b - > timer . seqno  -  hook_a - > timer . seqno ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  cmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  DTMF  hook  container  sort  comparison  function . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj_left  pointer  to  the  ( user - defined  part )  of  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj_right  pointer  to  the  ( user - defined  part )  of  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  flags  from  ao2_callback ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *    OBJ_POINTER  -  if  set ,  ' obj_right ' ,  is  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *    OBJ_KEY  -  if  set ,  ' obj_right ' ,  is  a  search  key  item  that  is  not  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *    OBJ_PARTIAL_KEY  -  if  set ,  ' obj_right ' ,  is  a  partial  search  key  item  that  is  not  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  < 0  if  obj_left  <  obj_right 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  = 0  if  obj_left  = =  obj_right 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  > 0  if  obj_left  >  obj_right 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_dtmf_hook_sort ( const  void  * obj_left ,  const  void  * obj_right ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  struct  ast_bridge_hook_dtmf  * hook_left  =  obj_left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_bridge_hook_dtmf  * hook_right  =  obj_right ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * right_key  =  obj_right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  cmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( flags  &  ( OBJ_POINTER  |  OBJ_KEY  |  OBJ_PARTIAL_KEY ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_POINTER : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										right_key  =  hook_right - > dtmf . code ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Fall through */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_KEY : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cmp  =  strcasecmp ( hook_left - > dtmf . code ,  right_key ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_PARTIAL_KEY : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cmp  =  strncasecmp ( hook_left - > dtmf . code ,  right_key ,  strlen ( right_key ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-06-26 12:43:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Callback for merging hook ao2_containers */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  merge_container_cb ( void  * obj ,  void  * data ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_link ( data ,  obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Wrapper for interval hooks that calls into the wrapped hook */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  interval_wrapper_cb ( struct  ast_bridge_channel  * bridge_channel ,  void  * obj )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_hook_timer  * hook  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  hook - > generic . callback ( bridge_channel ,  hook - > generic . hook_pvt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Destructor for the hook wrapper */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  interval_wrapper_pvt_dtor ( void  * obj )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Wrap the provided interval hook and add it to features */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  wrap_hook ( struct  ast_bridge_features  * features ,  struct  ast_bridge_hook_timer  * hook )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Break out of the current wrapper if it exists to avoid multiple layers */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( hook - > generic . callback  = =  interval_wrapper_cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hook  =  hook - > generic . hook_pvt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_interval_hook ( features ,  hook - > timer . flags ,  hook - > timer . interval , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										interval_wrapper_cb ,  ao2_bump ( hook ) ,  interval_wrapper_pvt_dtor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hook - > generic . remove_flags . flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_features_merge ( struct  ast_bridge_features  * into ,  const  struct  ast_bridge_features  * from )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_hook_timer  * hook ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Merge hook containers */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( from - > dtmf_hooks ,  0 ,  merge_container_cb ,  into - > dtmf_hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( from - > other_hooks ,  0 ,  merge_container_cb ,  into - > other_hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Merge hook heaps */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_heap_wrlock ( from - > interval_hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( idx  =  1 ;  ( hook  =  ast_heap_peek ( from - > interval_hooks ,  idx ) ) ;  idx + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										wrap_hook ( into ,  hook ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_heap_unlock ( from - > interval_hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Merge feature flags */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									into - > feature_flags . flags  | =  from - > feature_flags . flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									into - > usable  | =  from - > usable ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									into - > mute  | =  from - > mute ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									into - > dtmf_passthrough  | =  from - > dtmf_passthrough ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-15 18:20:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* XXX ASTERISK-21271 make ast_bridge_features_init() static when make ast_bridge_join() requires features to be allocated. */  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridge_features_init ( struct  ast_bridge_features  * features )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Zero out the structure */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									memset ( features ,  0 ,  sizeof ( * features ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Initialize the DTMF hooks container */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									features - > dtmf_hooks  =  ao2_container_alloc_list ( AO2_ALLOC_OPT_LOCK_MUTEX , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE ,  bridge_dtmf_hook_sort ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! features - > dtmf_hooks )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Initialize the miscellaneous other hooks container */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									features - > other_hooks  =  ao2_container_alloc_list ( AO2_ALLOC_OPT_LOCK_MUTEX ,  0 ,  NULL , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! features - > other_hooks )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Initialize the interval hooks heap */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									features - > interval_hooks  =  ast_heap_create ( 8 ,  interval_hook_time_cmp , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										offsetof ( struct  ast_bridge_hook_timer ,  timer . heap_index ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! features - > interval_hooks )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-15 12:17:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									features - > dtmf_passthrough  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-16 10:15:42 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									features - > text_messaging  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-15 12:17:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-15 18:20:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* XXX ASTERISK-21271 make ast_bridge_features_cleanup() static when make ast_bridge_join() requires features to be allocated. */  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_features_cleanup ( struct  ast_bridge_features  * features )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_hook_timer  * hook ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Destroy the interval hooks heap. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( features - > interval_hooks )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( ( hook  =  ast_heap_pop ( features - > interval_hooks ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( hook ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										features - > interval_hooks  =  ast_heap_destroy ( features - > interval_hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 21:13:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Destroy the miscellaneous other hooks container. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( features - > other_hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									features - > other_hooks  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Destroy the DTMF hooks container. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( features - > dtmf_hooks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									features - > dtmf_hooks  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_features_destroy ( struct  ast_bridge_features  * features )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! features )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_features_cleanup ( features ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_free ( features ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  ast_bridge_features  * ast_bridge_features_new ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_features  * features ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									features  =  ast_malloc ( sizeof ( * features ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( features )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_bridge_features_init ( features ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_features_destroy ( features ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											features  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  features ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_set_mixing_interval ( struct  ast_bridge  * bridge ,  unsigned  int  mixing_interval )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge - > softmix . internal_mixing_interval  =  mixing_interval ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-12 18:23:18 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_set_binaural_active ( struct  ast_bridge  * bridge ,  unsigned  int  binaural_active )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > softmix . binaural_active  =  binaural_active ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_set_internal_sample_rate ( struct  ast_bridge  * bridge ,  unsigned  int  sample_rate )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge - > softmix . internal_sample_rate  =  sample_rate ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-12-12 00:03:46 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_set_maximum_sample_rate ( struct  ast_bridge  * bridge ,  unsigned  int  sample_rate )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > softmix . maximum_sample_rate  =  sample_rate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  cleanup_video_mode ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( bridge - > softmix . video_mode . mode )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_NONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SINGLE_SRC : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . single_src_data . chan_vsrc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_unref ( bridge - > softmix . video_mode . mode_data . single_src_data . chan_vsrc ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_TALKER_SRC : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_vsrc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_unref ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_vsrc ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_old_vsrc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_unref ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_old_vsrc ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Add primitive SFU support to bridge_softmix.
This sets up the "plumbing" in bridge_softmix to
be able to accommodate Asterisk asking as an SFU
(selective forwarding unit) for conferences.
The way this works is that whenever a channel enters or leaves a
conference, all participants in the bridge get sent a stream topology
change request. The topologies consist of the channels' original
topology, along with video destination streams corresponding to each
participants' source video streams. So for instance, if Alice, Bob, and
Carol are in the conference, and each supplies one video stream, then
the topologies for each would look like so:
Alice:
Audio,
Source video(Alice),
Destination Video(Bob),
Destination video (Carol)
Bob:
Audio,
Source video(Bob)
Destination Video(Alice),
Destination video (Carol)
Carol:
Audio,
Source video(Carol)
Destination Video(Alice),
Destination video (Bob)
This way, video that arrives from a source video stream can then be
copied out to the destination video streams on the other participants'
channels.
Once the bridge gets told that a topology on a channel has changed, the
bridge constructs a map in order to get the video frames routed to the
proper destination streams. This is done using the bridge channel's
stream_map.
This change is bare-bones with regards to SFU support. Some key features
are missing at this point:
* Stream limits. This commit makes no effort to limit the number of
  streams on a specific channel. This means that if there were 50 video
  callers in a conference, bridge_softmix will happily send out topology
  change requests to every channel in the bridge, requesting 50+
  streams.
* Configuration. The plumbing has been added to bridge_softmix, but
  there has been nothing added as of yet to app_confbridge to enable SFU
  video mode.
* Testing. Some functions included here have unit tests.
  However, the functionality as a whole has only been verified by
  hand-tracing the code.
* Selectivenss. For a "selective" forwarding unit, this does not
  currently have any means of being selective.
* Features. Presumably, someone might wish to only receive video from
  specific sources. There are no external-facing functions at the moment
  that allow for users to select who they receive video from.
* Efficiency. The current scheme treats all video streams as being
  unidirectional. We could be re-using a source video stream as a
  desetnation, too. But to simplify things on this first round, I did it
  this way.
Change-Id: I7c44a829cc63acf8b596a337b2dc3c13898a6c4d
											 
										 
										
											2017-05-05 11:56:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SFU : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									memset ( & bridge - > softmix . video_mode ,  0 ,  sizeof ( bridge - > softmix . video_mode ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_set_single_src_video_mode ( struct  ast_bridge  * bridge ,  struct  ast_channel  * video_src_chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cleanup_video_mode ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge - > softmix . video_mode . mode  =  AST_BRIDGE_VIDEO_MODE_SINGLE_SRC ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-30 22:42:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( video_src_chan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge - > softmix . video_mode . mode_data . single_src_data . chan_vsrc  =  ast_channel_ref ( video_src_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_verb ( 5 ,  " Video source in bridge '%s' (%s) is now '%s' (%s) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > name ,  bridge - > uniqueid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( video_src_chan ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_uniqueid ( video_src_chan ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_indicate ( video_src_chan ,  AST_CONTROL_VIDUPDATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-08 10:11:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_publish_state ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_set_talker_src_video_mode ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cleanup_video_mode ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge - > softmix . video_mode . mode  =  AST_BRIDGE_VIDEO_MODE_TALKER_SRC ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-24 10:09:22 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_set_sfu_video_mode ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cleanup_video_mode ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > softmix . video_mode . mode  =  AST_BRIDGE_VIDEO_MODE_SFU ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-17 16:01:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_set_video_update_discard ( struct  ast_bridge  * bridge ,  unsigned  int  video_update_discard )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > softmix . video_mode . video_update_discard  =  video_update_discard ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-02 10:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_set_remb_send_interval ( struct  ast_bridge  * bridge ,  unsigned  int  remb_send_interval )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2018-04-04 15:12:50 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_assert ( bridge - > softmix . video_mode . mode  = =  AST_BRIDGE_VIDEO_MODE_SFU ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > softmix . video_mode . mode_data . sfu_data . remb_send_interval  =  remb_send_interval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_brige_set_remb_behavior ( struct  ast_bridge  * bridge ,  enum  ast_bridge_video_sfu_remb_behavior  behavior )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( bridge - > softmix . video_mode . mode  = =  AST_BRIDGE_VIDEO_MODE_SFU ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-02 10:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-04 15:12:50 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge - > softmix . video_mode . mode_data . sfu_data . remb_behavior  =  behavior ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-02 10:53:17 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-09-24 12:46:15 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_set_remb_estimated_bitrate ( struct  ast_bridge  * bridge ,  float  estimated_bitrate )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( bridge - > softmix . video_mode . mode  = =  AST_BRIDGE_VIDEO_MODE_SFU ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > softmix . video_mode . mode_data . sfu_data . estimated_bitrate  =  estimated_bitrate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_update_talker_src_video_mode ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan ,  int  talker_energy ,  int  is_keyframe )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_video_talker_src_data  * data ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If the channel doesn't support video, we don't care about it */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
 1. Asterisk was limited in how many formats it could handle.
 2. Formats, being a bit field, could not include any attribute information.
    A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
 * The ast_format structure is reference counted. This removed a large amount
   of the memory allocations and copying that was done in prior versions.
 * In order to prevent race conditions while keeping things performant, the
   ast_format structure is immutable by convention and lock-free. Violate this
   tenet at your peril!
 * Because formats are reference counted, codecs are also reference counted.
   The Asterisk core generally provides built-in codecs and caches the
   ast_format structures created to represent them. Generally, to prevent
   inordinate amounts of module reference bumping, codecs and formats can be
   added at run-time but cannot be removed.
 * All compatibility with the bit field representation of codecs/formats has
   been moved to a compatibility API. The primary user of this representation
   is chan_iax2, which must continue to maintain its bit-field usage of formats
   for interoperability concerns.
 * When a format is negotiated with attributes, or when a format cannot be
   represented by one of the cached formats, a new format object is created or
   cloned from an existing format. That format may have the same codec
   underlying it, but is a different format than a version of the format with
   different attributes or without attributes.
 * While formats are reference counted objects, the reference count maintained
   on the format should be manipulated with care. Formats are generally cached
   and will persist for the lifetime of Asterisk and do not explicitly need
   to have their lifetime modified. An exception to this is when the user of a
   format does not know where the format came from *and* the user may outlive
   the provider of the format. This occurs, for example, when a format is read
   from a channel: the channel may have a format with attributes (hence,
   non-cached) and the user of the format may last longer than the channel (if
   the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
  https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
 https://reviewboard.asterisk.org/r/3814
 https://reviewboard.asterisk.org/r/3808
 https://reviewboard.asterisk.org/r/3805
 https://reviewboard.asterisk.org/r/3803
 https://reviewboard.asterisk.org/r/3801
 https://reviewboard.asterisk.org/r/3798
 https://reviewboard.asterisk.org/r/3800
 https://reviewboard.asterisk.org/r/3794
 https://reviewboard.asterisk.org/r/3793
 https://reviewboard.asterisk.org/r/3792
 https://reviewboard.asterisk.org/r/3791
 https://reviewboard.asterisk.org/r/3790
 https://reviewboard.asterisk.org/r/3789
 https://reviewboard.asterisk.org/r/3788
 https://reviewboard.asterisk.org/r/3787
 https://reviewboard.asterisk.org/r/3786
 https://reviewboard.asterisk.org/r/3784
 https://reviewboard.asterisk.org/r/3783
 https://reviewboard.asterisk.org/r/3778
 https://reviewboard.asterisk.org/r/3774
 https://reviewboard.asterisk.org/r/3775
 https://reviewboard.asterisk.org/r/3772
 https://reviewboard.asterisk.org/r/3761
 https://reviewboard.asterisk.org/r/3754
 https://reviewboard.asterisk.org/r/3753
 https://reviewboard.asterisk.org/r/3751
 https://reviewboard.asterisk.org/r/3750
 https://reviewboard.asterisk.org/r/3748
 https://reviewboard.asterisk.org/r/3747
 https://reviewboard.asterisk.org/r/3746
 https://reviewboard.asterisk.org/r/3742
 https://reviewboard.asterisk.org/r/3740
 https://reviewboard.asterisk.org/r/3739
 https://reviewboard.asterisk.org/r/3738
 https://reviewboard.asterisk.org/r/3737
 https://reviewboard.asterisk.org/r/3736
 https://reviewboard.asterisk.org/r/3734
 https://reviewboard.asterisk.org/r/3722
 https://reviewboard.asterisk.org/r/3713
 https://reviewboard.asterisk.org/r/3703
 https://reviewboard.asterisk.org/r/3689
 https://reviewboard.asterisk.org/r/3687
 https://reviewboard.asterisk.org/r/3674
 https://reviewboard.asterisk.org/r/3671
 https://reviewboard.asterisk.org/r/3667
 https://reviewboard.asterisk.org/r/3665
 https://reviewboard.asterisk.org/r/3625
 https://reviewboard.asterisk.org/r/3602
 https://reviewboard.asterisk.org/r/3519
 https://reviewboard.asterisk.org/r/3518
 https://reviewboard.asterisk.org/r/3516
 https://reviewboard.asterisk.org/r/3515
 https://reviewboard.asterisk.org/r/3512
 https://reviewboard.asterisk.org/r/3506
 https://reviewboard.asterisk.org/r/3413
 https://reviewboard.asterisk.org/r/3410
 https://reviewboard.asterisk.org/r/3387
 https://reviewboard.asterisk.org/r/3388
 https://reviewboard.asterisk.org/r/3389
 https://reviewboard.asterisk.org/r/3390
 https://reviewboard.asterisk.org/r/3321
 https://reviewboard.asterisk.org/r/3320
 https://reviewboard.asterisk.org/r/3319
 https://reviewboard.asterisk.org/r/3318
 https://reviewboard.asterisk.org/r/3266
 https://reviewboard.asterisk.org/r/3265
 https://reviewboard.asterisk.org/r/3234
 https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
  media_formats_translation_core.diff uploaded by kharwell (License 6464)
  rb3506.diff uploaded by mjordan (License 6283)
  media_format_app_file.diff uploaded by kharwell (License 6464) 
  misc-2.diff uploaded by file (License 5000)
  chan_mild-3.diff uploaded by file (License 5000) 
  chan_obscure.diff uploaded by file (License 5000) 
  jingle.diff uploaded by file (License 5000) 
  funcs.diff uploaded by file (License 5000) 
  formats.diff uploaded by file (License 5000) 
  core.diff uploaded by file (License 5000) 
  bridges.diff uploaded by file (License 5000) 
  mf-codecs-2.diff uploaded by file (License 5000) 
  mf-app_fax.diff uploaded by file (License 5000) 
  mf-apps-3.diff uploaded by file (License 5000) 
  media-formats-3.diff uploaded by file (License 5000) 
ASTERISK-23715
  rb3713.patch uploaded by coreyfarrell (License 5909)
  rb3689.patch uploaded by mjordan (License 6283)
  
ASTERISK-23957
  rb3722.patch uploaded by mjordan (License 6283) 
  mf-attributes-3.diff uploaded by file (License 5000) 
ASTERISK-23958
Tested by: jrose
  rb3822.patch uploaded by coreyfarrell (License 5909) 
  rb3800.patch uploaded by jrose (License 6182)
  chan_sip.diff uploaded by mjordan (License 6283) 
  rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
  sip_cleanup.diff uploaded by opticron (License 6273)
  chan_sip_caps.diff uploaded by mjordan (License 6283) 
  rb3751.patch uploaded by coreyfarrell (License 5909) 
  chan_sip-3.diff uploaded by file (License 5000) 
ASTERISK-23960 #close
Tested by: opticron
  direct_media.diff uploaded by opticron (License 6273) 
  pjsip-direct-media.diff uploaded by file (License 5000) 
  format_cap_remove.diff uploaded by opticron (License 6273) 
  media_format_fixes.diff uploaded by opticron (License 6273) 
  chan_pjsip-2.diff uploaded by file (License 5000) 
ASTERISK-23966 #close
Tested by: rmudgett
  rb3803.patch uploaded by rmudgetti (License 5621)
  chan_dahdi.diff uploaded by file (License 5000) 
  
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
  rb3814.patch uploaded by rmudgett (License 5621) 
  moh_cleanup.diff uploaded by opticron (License 6273) 
  bridge_leak.diff uploaded by opticron (License 6273) 
  translate.diff uploaded by file (License 5000) 
  rb3795.patch uploaded by rmudgett (License 5621) 
  tls_fix.diff uploaded by mjordan (License 6283) 
  fax-mf-fix-2.diff uploaded by file (License 5000) 
  rtp_transfer_stuff uploaded by mjordan (License 6283) 
  rb3787.patch uploaded by rmudgett (License 5621) 
  media-formats-explicit-translate-format-3.diff uploaded by file (License 5000) 
  format_cache_case_fix.diff uploaded by opticron (License 6273) 
  rb3774.patch uploaded by rmudgett (License 5621) 
  rb3775.patch uploaded by rmudgett (License 5621) 
  rtp_engine_fix.diff uploaded by opticron (License 6273) 
  rtp_crash_fix.diff uploaded by opticron (License 6273) 
  rb3753.patch uploaded by mjordan (License 6283) 
  rb3750.patch uploaded by mjordan (License 6283) 
  rb3748.patch uploaded by rmudgett (License 5621) 
  media_format_fixes.diff uploaded by opticron (License 6273) 
  rb3740.patch uploaded by mjordan (License 6283) 
  rb3739.patch uploaded by mjordan (License 6283) 
  rb3734.patch uploaded by mjordan (License 6283) 
  rb3689.patch uploaded by mjordan (License 6283) 
  rb3674.patch uploaded by coreyfarrell (License 5909) 
  rb3671.patch uploaded by coreyfarrell (License 5909) 
  rb3667.patch uploaded by coreyfarrell (License 5909) 
  rb3665.patch uploaded by mjordan (License 6283) 
  rb3625.patch uploaded by coreyfarrell (License 5909) 
  rb3602.patch uploaded by coreyfarrell (License 5909) 
  format_compatibility-2.diff uploaded by file (License 5000) 
  core.diff uploaded by file (License 5000) 
  
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-20 22:06:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_format_cap_has_type ( ast_channel_nativeformats ( chan ) ,  AST_MEDIA_TYPE_VIDEO ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									data  =  & bridge - > softmix . video_mode . mode_data . talker_src_data ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( data - > chan_vsrc  = =  chan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data - > average_talking_energy  =  talker_energy ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ( data - > average_talking_energy  <  talker_energy )  & &  is_keyframe )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( data - > chan_old_vsrc )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-20 11:23:08 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											data - > chan_old_vsrc  =  ast_channel_unref ( data - > chan_old_vsrc ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( data - > chan_vsrc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											data - > chan_old_vsrc  =  data - > chan_vsrc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_indicate ( data - > chan_old_vsrc ,  AST_CONTROL_VIDUPDATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data - > chan_vsrc  =  ast_channel_ref ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data - > average_talking_energy  =  talker_energy ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-04 15:36:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_verb ( 5 ,  " Video source in bridge '%s' (%s) is now '%s' (%s) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > name ,  bridge - > uniqueid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( data - > chan_vsrc ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_uniqueid ( data - > chan_vsrc ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-08 10:11:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_publish_state ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_indicate ( data - > chan_vsrc ,  AST_CONTROL_VIDUPDATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ( data - > average_talking_energy  <  talker_energy )  & &  ! is_keyframe )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_indicate ( chan ,  AST_CONTROL_VIDUPDATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! data - > chan_vsrc  & &  is_keyframe )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data - > chan_vsrc  =  ast_channel_ref ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data - > average_talking_energy  =  talker_energy ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-04 15:36:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_verb ( 5 ,  " Video source in bridge '%s' (%s) is now '%s' (%s) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > name ,  bridge - > uniqueid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( data - > chan_vsrc ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_uniqueid ( data - > chan_vsrc ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-08 10:11:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_publish_state ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_indicate ( chan ,  AST_CONTROL_VIDUPDATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! data - > chan_old_vsrc  & &  is_keyframe )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data - > chan_old_vsrc  =  ast_channel_ref ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_indicate ( chan ,  AST_CONTROL_VIDUPDATE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_number_video_src ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( bridge - > softmix . video_mode . mode )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_NONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SINGLE_SRC : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . single_src_data . chan_vsrc )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_TALKER_SRC : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_vsrc )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_old_vsrc )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Add primitive SFU support to bridge_softmix.
This sets up the "plumbing" in bridge_softmix to
be able to accommodate Asterisk asking as an SFU
(selective forwarding unit) for conferences.
The way this works is that whenever a channel enters or leaves a
conference, all participants in the bridge get sent a stream topology
change request. The topologies consist of the channels' original
topology, along with video destination streams corresponding to each
participants' source video streams. So for instance, if Alice, Bob, and
Carol are in the conference, and each supplies one video stream, then
the topologies for each would look like so:
Alice:
Audio,
Source video(Alice),
Destination Video(Bob),
Destination video (Carol)
Bob:
Audio,
Source video(Bob)
Destination Video(Alice),
Destination video (Carol)
Carol:
Audio,
Source video(Carol)
Destination Video(Alice),
Destination video (Bob)
This way, video that arrives from a source video stream can then be
copied out to the destination video streams on the other participants'
channels.
Once the bridge gets told that a topology on a channel has changed, the
bridge constructs a map in order to get the video frames routed to the
proper destination streams. This is done using the bridge channel's
stream_map.
This change is bare-bones with regards to SFU support. Some key features
are missing at this point:
* Stream limits. This commit makes no effort to limit the number of
  streams on a specific channel. This means that if there were 50 video
  callers in a conference, bridge_softmix will happily send out topology
  change requests to every channel in the bridge, requesting 50+
  streams.
* Configuration. The plumbing has been added to bridge_softmix, but
  there has been nothing added as of yet to app_confbridge to enable SFU
  video mode.
* Testing. Some functions included here have unit tests.
  However, the functionality as a whole has only been verified by
  hand-tracing the code.
* Selectivenss. For a "selective" forwarding unit, this does not
  currently have any means of being selective.
* Features. Presumably, someone might wish to only receive video from
  specific sources. There are no external-facing functions at the moment
  that allow for users to select who they receive video from.
* Efficiency. The current scheme treats all video streams as being
  unidirectional. We could be re-using a source video stream as a
  desetnation, too. But to simplify things on this first round, I did it
  this way.
Change-Id: I7c44a829cc63acf8b596a337b2dc3c13898a6c4d
											 
										 
										
											2017-05-05 11:56:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SFU : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_bridge_is_video_src ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( bridge - > softmix . video_mode . mode )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_NONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SINGLE_SRC : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . single_src_data . chan_vsrc  = =  chan )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_TALKER_SRC : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_vsrc  = =  chan )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_old_vsrc  = =  chan )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Add primitive SFU support to bridge_softmix.
This sets up the "plumbing" in bridge_softmix to
be able to accommodate Asterisk asking as an SFU
(selective forwarding unit) for conferences.
The way this works is that whenever a channel enters or leaves a
conference, all participants in the bridge get sent a stream topology
change request. The topologies consist of the channels' original
topology, along with video destination streams corresponding to each
participants' source video streams. So for instance, if Alice, Bob, and
Carol are in the conference, and each supplies one video stream, then
the topologies for each would look like so:
Alice:
Audio,
Source video(Alice),
Destination Video(Bob),
Destination video (Carol)
Bob:
Audio,
Source video(Bob)
Destination Video(Alice),
Destination video (Carol)
Carol:
Audio,
Source video(Carol)
Destination Video(Alice),
Destination video (Bob)
This way, video that arrives from a source video stream can then be
copied out to the destination video streams on the other participants'
channels.
Once the bridge gets told that a topology on a channel has changed, the
bridge constructs a map in order to get the video frames routed to the
proper destination streams. This is done using the bridge channel's
stream_map.
This change is bare-bones with regards to SFU support. Some key features
are missing at this point:
* Stream limits. This commit makes no effort to limit the number of
  streams on a specific channel. This means that if there were 50 video
  callers in a conference, bridge_softmix will happily send out topology
  change requests to every channel in the bridge, requesting 50+
  streams.
* Configuration. The plumbing has been added to bridge_softmix, but
  there has been nothing added as of yet to app_confbridge to enable SFU
  video mode.
* Testing. Some functions included here have unit tests.
  However, the functionality as a whole has only been verified by
  hand-tracing the code.
* Selectivenss. For a "selective" forwarding unit, this does not
  currently have any means of being selective.
* Features. Presumably, someone might wish to only receive video from
  specific sources. There are no external-facing functions at the moment
  that allow for users to select who they receive video from.
* Efficiency. The current scheme treats all video streams as being
  unidirectional. We could be re-using a source video stream as a
  desetnation, too. But to simplify things on this first round, I did it
  this way.
Change-Id: I7c44a829cc63acf8b596a337b2dc3c13898a6c4d
											 
										 
										
											2017-05-05 11:56:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SFU : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_bridge_remove_video_src ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( bridge - > softmix . video_mode . mode )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_NONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SINGLE_SRC : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . single_src_data . chan_vsrc  = =  chan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( bridge - > softmix . video_mode . mode_data . single_src_data . chan_vsrc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_unref ( bridge - > softmix . video_mode . mode_data . single_src_data . chan_vsrc ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											bridge - > softmix . video_mode . mode_data . single_src_data . chan_vsrc  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_TALKER_SRC : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_vsrc  = =  chan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_vsrc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_unref ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_vsrc ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											bridge - > softmix . video_mode . mode_data . talker_src_data . chan_vsrc  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge - > softmix . video_mode . mode_data . talker_src_data . average_talking_energy  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_old_vsrc  = =  chan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_old_vsrc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_unref ( bridge - > softmix . video_mode . mode_data . talker_src_data . chan_old_vsrc ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 19:14:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											bridge - > softmix . video_mode . mode_data . talker_src_data . chan_old_vsrc  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Add primitive SFU support to bridge_softmix.
This sets up the "plumbing" in bridge_softmix to
be able to accommodate Asterisk asking as an SFU
(selective forwarding unit) for conferences.
The way this works is that whenever a channel enters or leaves a
conference, all participants in the bridge get sent a stream topology
change request. The topologies consist of the channels' original
topology, along with video destination streams corresponding to each
participants' source video streams. So for instance, if Alice, Bob, and
Carol are in the conference, and each supplies one video stream, then
the topologies for each would look like so:
Alice:
Audio,
Source video(Alice),
Destination Video(Bob),
Destination video (Carol)
Bob:
Audio,
Source video(Bob)
Destination Video(Alice),
Destination video (Carol)
Carol:
Audio,
Source video(Carol)
Destination Video(Alice),
Destination video (Bob)
This way, video that arrives from a source video stream can then be
copied out to the destination video streams on the other participants'
channels.
Once the bridge gets told that a topology on a channel has changed, the
bridge constructs a map in order to get the video frames routed to the
proper destination streams. This is done using the bridge channel's
stream_map.
This change is bare-bones with regards to SFU support. Some key features
are missing at this point:
* Stream limits. This commit makes no effort to limit the number of
  streams on a specific channel. This means that if there were 50 video
  callers in a conference, bridge_softmix will happily send out topology
  change requests to every channel in the bridge, requesting 50+
  streams.
* Configuration. The plumbing has been added to bridge_softmix, but
  there has been nothing added as of yet to app_confbridge to enable SFU
  video mode.
* Testing. Some functions included here have unit tests.
  However, the functionality as a whole has only been verified by
  hand-tracing the code.
* Selectivenss. For a "selective" forwarding unit, this does not
  currently have any means of being selective.
* Features. Presumably, someone might wish to only receive video from
  specific sources. There are no external-facing functions at the moment
  that allow for users to select who they receive video from.
* Efficiency. The current scheme treats all video streams as being
  unidirectional. We could be re-using a source video stream as a
  desetnation, too. But to simplify things on this first round, I did it
  this way.
Change-Id: I7c44a829cc63acf8b596a337b2dc3c13898a6c4d
											 
										 
										
											2017-05-05 11:56:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SFU : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-06-26 21:45:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2012-06-26 21:45:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-11-08 10:11:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  char  * ast_bridge_video_mode_to_string ( enum  ast_bridge_video_mode_type  video_mode )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( video_mode )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_TALKER_SRC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  " talker " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SINGLE_SRC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  " single " ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Add primitive SFU support to bridge_softmix.
This sets up the "plumbing" in bridge_softmix to
be able to accommodate Asterisk asking as an SFU
(selective forwarding unit) for conferences.
The way this works is that whenever a channel enters or leaves a
conference, all participants in the bridge get sent a stream topology
change request. The topologies consist of the channels' original
topology, along with video destination streams corresponding to each
participants' source video streams. So for instance, if Alice, Bob, and
Carol are in the conference, and each supplies one video stream, then
the topologies for each would look like so:
Alice:
Audio,
Source video(Alice),
Destination Video(Bob),
Destination video (Carol)
Bob:
Audio,
Source video(Bob)
Destination Video(Alice),
Destination video (Carol)
Carol:
Audio,
Source video(Carol)
Destination Video(Alice),
Destination video (Bob)
This way, video that arrives from a source video stream can then be
copied out to the destination video streams on the other participants'
channels.
Once the bridge gets told that a topology on a channel has changed, the
bridge constructs a map in order to get the video frames routed to the
proper destination streams. This is done using the bridge channel's
stream_map.
This change is bare-bones with regards to SFU support. Some key features
are missing at this point:
* Stream limits. This commit makes no effort to limit the number of
  streams on a specific channel. This means that if there were 50 video
  callers in a conference, bridge_softmix will happily send out topology
  change requests to every channel in the bridge, requesting 50+
  streams.
* Configuration. The plumbing has been added to bridge_softmix, but
  there has been nothing added as of yet to app_confbridge to enable SFU
  video mode.
* Testing. Some functions included here have unit tests.
  However, the functionality as a whole has only been verified by
  hand-tracing the code.
* Selectivenss. For a "selective" forwarding unit, this does not
  currently have any means of being selective.
* Features. Presumably, someone might wish to only receive video from
  specific sources. There are no external-facing functions at the moment
  that allow for users to select who they receive video from.
* Efficiency. The current scheme treats all video streams as being
  unidirectional. We could be re-using a source video stream as a
  desetnation, too. But to simplify things on this first round, I did it
  this way.
Change-Id: I7c44a829cc63acf8b596a337b2dc3c13898a6c4d
											 
										 
										
											2017-05-05 11:56:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_SFU : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  " sfu " ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-08 10:11:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_VIDEO_MODE_NONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  " none " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-16 06:02:19 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_set_send_sdp_label ( struct  ast_bridge  * bridge ,  unsigned  int  send_sdp_label )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge - > softmix . send_sdp_label  =  send_sdp_label ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  hash ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  channel_cmp ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  struct  ast_channel  * left  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_channel  * right  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * right_name  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  cmp ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-21 18:45:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  cmp  ?  0  :  CMP_MATCH ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ao2_container  * ast_bridge_peers_nolock ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ao2_container  * channels ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * iter ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-16 15:11:06 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									channels  =  ao2_container_alloc_hash ( AO2_ALLOC_OPT_LOCK_NOLOCK ,  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										13 ,  channel_hash ,  NULL ,  channel_cmp ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! channels )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  iter ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_link ( channels ,  iter - > chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  channels ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ao2_container  * ast_bridge_peers ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_container  * channels ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									channels  =  ast_bridge_peers_nolock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  channels ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_channel  * ast_bridge_peer_nolock ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_channel  * peer  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * iter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Asking for the peer channel only makes sense on a two-party bridge. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > num_channels  = =  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  bridge - > technology - > capabilities 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											&  ( AST_BRIDGE_CAPABILITY_NATIVE  |  AST_BRIDGE_CAPABILITY_1TO1MIX ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  in_bridge  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_TRAVERSE ( & bridge - > channels ,  iter ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( iter - > chan  ! =  chan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer  =  iter - > chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												in_bridge  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( in_bridge  & &  peer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_ref ( peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2012-06-26 21:45:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  peer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_channel  * ast_bridge_peer ( struct  ast_bridge  * bridge ,  struct  ast_channel  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * peer ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									peer  =  ast_bridge_peer_nolock ( bridge ,  chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  peer ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Transfer  an  entire  bridge  to  a  specific  destination . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  creates  a  local  channel  to  dial  out  and  swaps  the  called  local  channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  with  the  transferer  channel .  By  doing  so ,  all  participants  in  the  bridge  are 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  connected  to  the  specified  destination . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  While  this  means  of  transferring  would  work  for  both  two - party  and  multi - party 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  bridges ,  this  method  is  only  used  for  multi - party  bridges  since  this  method  would 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  be  less  efficient  for  two - party  bridges . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-20 13:06:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  is_external  Whether  the  transfer  is  externally  initiated 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  transferer  The  channel  performing  a  transfer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  The  bridge  where  the  transfer  is  being  performed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  exten  The  destination  extension  for  the  blind  transfer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  context  The  destination  context  for  the  blind  transfer 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  transferee  The  party  being  transferred  if  there  is  only  one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  new_channel_cb  Callback  to  call  on  channel  that  is  created  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         facilitate  the  blind  transfer . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  user_data_wrapper  User - provided  data  needed  in  new_channel_cb 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  transfer_message  The  Stasis  publication  for  this  transfer . 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-20 13:06:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ return  The  success  or  failure  of  the  operation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-20 13:06:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  ast_transfer_result  blind_transfer_bridge ( int  is_external ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_channel  * transferer ,  struct  ast_bridge  * bridge , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  char  * exten ,  const  char  * context ,  struct  ast_channel  * transferee , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										transfer_channel_cb  new_channel_cb , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  transfer_channel_data  * user_data_wrapper , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_blind_transfer_message  * transfer_message ) 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_channel  * local ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  chan_name [ AST_MAX_EXTENSION  +  AST_MAX_CONTEXT  +  2 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  cause ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 21:14:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_format_cap  * caps ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( transferer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									caps  =  ao2_bump ( ast_channel_nativeformats ( transferer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									snprintf ( chan_name ,  sizeof ( chan_name ) ,  " %s@%s " ,  exten ,  context ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 21:14:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									local  =  ast_request ( " Local " ,  caps ,  NULL ,  transferer , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											chan_name ,  & cause ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 21:14:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( caps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! local )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2012-06-26 21:45:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												accountcode: Slightly change accountcode propagation.
The previous behavior was to simply set the accountcode of an outgoing
channel to the accountcode of the channel initiating the call.  It was
done this way a long time ago to allow the accountcode set on the SIP/100
channel to be propagated to a local channel so the dialplan execution on
the Local;2 channel would have the SIP/100 accountcode available.
SIP/100 -> Local;1/Local;2 -> SIP/200
Propagating the SIP/100 accountcode to the local channels is very useful.
Without any dialplan manipulation, all channels in this call would have
the same accountcode.
Using dialplan, you can set a different accountcode on the SIP/200 channel
either by setting the accountcode on the Local;2 channel or by the Dial
application's b(pre-dial), M(macro) or U(gosub) options, or by the
FollowMe application's b(pre-dial) option, or by the Queue application's
macro or gosub options.  Before Asterisk v12, the altered accountcode on
SIP/200 will remain until the local channels optimize out and the
accountcode would change to the SIP/100 accountcode.
Asterisk v1.8 attempted to add peeraccount support but ultimately had to
punt on the support.  The peeraccount support was rendered useless because
of how the CDR code needed to unconditionally force the caller's
accountcode onto the peer channel's accountcode.  The CEL events were thus
intentionally made to always use the channel's accountcode as the
peeraccount value.
With the arrival of Asterisk v12, the situation has improved somewhat so
peeraccount support can be made to work.  Using the indicated example, the
the accountcode values become as follows when the peeraccount is set on
SIP/100 before calling SIP/200:
SIP/100 ---> Local;1 ---- Local;2 ---> SIP/200
acct: 100 \/ acct: 200 \/ acct: 100 \/ acct: 200
peer: 200 /\ peer: 100 /\ peer: 200 /\ peer: 100
If a channel already has an accountcode it can only change by the
following explicit user actions:
1) A channel originate method that can specify an accountcode to use.
2) The calling channel propagating its non-empty peeraccount or its
non-empty accountcode if the peeraccount was empty to the outgoing
channel's accountcode before initiating the dial.  e.g., Dial and
FollowMe.  The exception to this propagation method is Queue.  Queue will
only propagate peeraccounts this way only if the outgoing channel does not
have an accountcode.
3) Dialplan using CHANNEL(accountcode).
4) Dialplan using CHANNEL(peeraccount) on the other end of a local
channel pair.
If a channel does not have an accountcode it can get one from the
following places:
1) The channel driver's configuration at channel creation.
2) Explicit user action as already indicated.
3) Entering a basic or stasis-mixing bridge from a peer channel's
peeraccount value.
You can specify the accountcode for an outgoing channel by setting the
CHANNEL(peeraccount) before using the Dial, FollowMe, and Queue
applications.  Queue adds the wrinkle that it will not overwrite an
existing accountcode on the outgoing channel with the calling channels
values.
Accountcode and peeraccount values propagate to an outgoing channel before
dialing.  Accountcodes also propagate when channels enter or leave a basic
or stasis-mixing bridge.  The peeraccount value only makes sense for
mixing bridges with two channels; it is meaningless otherwise.
* Made peeraccount functional by changing accountcode propagation as
described above.
* Fixed CEL extracting the wrong ie value for the peeraccount.  This was
done intentionally in Asterisk v1.8 when that version had to punt on
peeraccount.
* Fixed a few places dealing with accountcodes that were reading from
channels without the lock held.
AFS-65 #close
Review: https://reviewboard.asterisk.org/r/3601/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419520 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-24 22:48:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_lock_both ( local ,  transferer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_req_accountcodes ( local ,  transferer ,  AST_CHANNEL_REQUESTOR_REPLACEMENT ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									transfer_message - > replace_channel  =  ast_channel_snapshot_get_latest ( ast_channel_uniqueid ( local ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! transfer_message - > replace_channel )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_hangup ( local ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									pbx_builtin_setvar_helper ( local ,  BLINDTRANSFER ,  ast_channel_name ( transferer ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												accountcode: Slightly change accountcode propagation.
The previous behavior was to simply set the accountcode of an outgoing
channel to the accountcode of the channel initiating the call.  It was
done this way a long time ago to allow the accountcode set on the SIP/100
channel to be propagated to a local channel so the dialplan execution on
the Local;2 channel would have the SIP/100 accountcode available.
SIP/100 -> Local;1/Local;2 -> SIP/200
Propagating the SIP/100 accountcode to the local channels is very useful.
Without any dialplan manipulation, all channels in this call would have
the same accountcode.
Using dialplan, you can set a different accountcode on the SIP/200 channel
either by setting the accountcode on the Local;2 channel or by the Dial
application's b(pre-dial), M(macro) or U(gosub) options, or by the
FollowMe application's b(pre-dial) option, or by the Queue application's
macro or gosub options.  Before Asterisk v12, the altered accountcode on
SIP/200 will remain until the local channels optimize out and the
accountcode would change to the SIP/100 accountcode.
Asterisk v1.8 attempted to add peeraccount support but ultimately had to
punt on the support.  The peeraccount support was rendered useless because
of how the CDR code needed to unconditionally force the caller's
accountcode onto the peer channel's accountcode.  The CEL events were thus
intentionally made to always use the channel's accountcode as the
peeraccount value.
With the arrival of Asterisk v12, the situation has improved somewhat so
peeraccount support can be made to work.  Using the indicated example, the
the accountcode values become as follows when the peeraccount is set on
SIP/100 before calling SIP/200:
SIP/100 ---> Local;1 ---- Local;2 ---> SIP/200
acct: 100 \/ acct: 200 \/ acct: 100 \/ acct: 200
peer: 200 /\ peer: 100 /\ peer: 200 /\ peer: 100
If a channel already has an accountcode it can only change by the
following explicit user actions:
1) A channel originate method that can specify an accountcode to use.
2) The calling channel propagating its non-empty peeraccount or its
non-empty accountcode if the peeraccount was empty to the outgoing
channel's accountcode before initiating the dial.  e.g., Dial and
FollowMe.  The exception to this propagation method is Queue.  Queue will
only propagate peeraccounts this way only if the outgoing channel does not
have an accountcode.
3) Dialplan using CHANNEL(accountcode).
4) Dialplan using CHANNEL(peeraccount) on the other end of a local
channel pair.
If a channel does not have an accountcode it can get one from the
following places:
1) The channel driver's configuration at channel creation.
2) Explicit user action as already indicated.
3) Entering a basic or stasis-mixing bridge from a peer channel's
peeraccount value.
You can specify the accountcode for an outgoing channel by setting the
CHANNEL(peeraccount) before using the Dial, FollowMe, and Queue
applications.  Queue adds the wrinkle that it will not overwrite an
existing accountcode on the outgoing channel with the calling channels
values.
Accountcode and peeraccount values propagate to an outgoing channel before
dialing.  Accountcodes also propagate when channels enter or leave a basic
or stasis-mixing bridge.  The peeraccount value only makes sense for
mixing bridges with two channels; it is meaningless otherwise.
* Made peeraccount functional by changing accountcode propagation as
described above.
* Fixed CEL extracting the wrong ie value for the peeraccount.  This was
done intentionally in Asterisk v1.8 when that version had to punt on
peeraccount.
* Fixed a few places dealing with accountcodes that were reading from
channels without the lock held.
AFS-65 #close
Review: https://reviewboard.asterisk.org/r/3601/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419520 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-24 22:48:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_unlock ( local ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( new_channel_cb )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-22 15:52:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										new_channel_cb ( local ,  user_data_wrapper ,  AST_BRIDGE_TRANSFER_MULTI_PARTY ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_call ( local ,  chan_name ,  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_hangup ( local ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-13 22:19:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_bridge_impart ( bridge ,  local ,  transferer ,  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_BRIDGE_IMPART_CHAN_INDEPENDENT ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_hangup ( local ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  AST_BRIDGE_TRANSFER_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Get  the  transferee  channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  is  only  applicable  to  cases  where  a  transfer  is  occurring  on  a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  two - party  bridge .  The  channels  container  passed  in  is  expected  to  only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  contain  two  channels ,  the  transferer  and  the  transferee .  The  transferer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  channel  is  passed  in  as  a  parameter  to  ensure  we  don ' t  return  it  as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  transferee  channel . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  channels  A  two - channel  container  containing  the  transferer  and  transferee 
							 
						 
					
						
							
								
									
										
										
											
												docs: Fix various typos in main/
Found via `codespell -q 3 -S "./CREDITS" -L abd,asent,atleast,childrens,contentn,crypted,dne,durationm,exten,inout,leapyear,nd,oclock,offsetp,ot,parm,parms,requestor,ser,slanguage,slin,thirdparty,varn,varns,ues`
											 
										 
										
											2025-02-04 05:53:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  transferer  The  party  that  is  transferring  the  call 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ return  The  party  that  is  being  transferred 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_channel  * get_transferee ( struct  ao2_container  * channels ,  struct  ast_channel  * transferer )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_iterator  channel_iter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * transferee ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( channel_iter  =  ao2_iterator_init ( channels ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( transferee  =  ao2_iterator_next ( & channel_iter ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_cleanup ( transferee ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( transferee  ! =  transferer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & channel_iter ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  transferee ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Perform  an  attended  transfer  of  a  bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  performs  an  attended  transfer  of  an  entire  bridge  to  a  target . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  target  varies ,  depending  on  what  bridges  exist  during  the  transfer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  attempt . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  If  two  bridges  exist ,  then  a  local  channel  is  created  to  link  the  two 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-11 22:57:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  bridges  together . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  If  only  one  bridge  exists ,  then  a  local  channel  is  created  with  one  end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  placed  into  the  existing  bridge  and  the  other  end  masquerading  into 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  unbridged  channel . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan1  Transferer  channel .  Guaranteed  to  be  bridged . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan2  Other  transferer  channel .  May  or  may  not  be  bridged . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge1  Bridge  that  chan1  is  in .  Guaranteed  to  be  non - NULL . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge2  Bridge  that  chan2  is  in .  If  NULL ,  then  chan2  is  not  bridged . 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-19 16:47:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  transfer_msg  Data  to  publish  for  a  stasis  attended  transfer  message . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ retval  AST_BRIDGE_TRANSFER_FAIL  Internal  error  occurred 
							 
						 
					
						
							
								
									
										
										
											
												docs: Fix various typos in main/
Found via `codespell -q 3 -S "./CREDITS" -L abd,asent,atleast,childrens,contentn,crypted,dne,durationm,exten,inout,leapyear,nd,oclock,offsetp,ot,parm,parms,requestor,ser,slanguage,slin,thirdparty,varn,varns,ues`
											 
										 
										
											2025-02-04 05:53:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ retval  AST_BRIDGE_TRANSFER_SUCCESS  Successfully  transferred  the  bridge 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  enum  ast_transfer_result  attended_transfer_bridge ( struct  ast_channel  * chan1 ,  
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_channel  * chan2 ,  struct  ast_bridge  * bridge1 ,  struct  ast_bridge  * bridge2 , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_attended_transfer_message  * transfer_msg ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-07-08 14:56:10 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define BRIDGE_LOCK_ONE_OR_BOTH(b1, b2) \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									do  {  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( b2 )  {  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_lock_both ( b1 ,  b2 ) ;  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  {  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_lock ( b1 ) ;  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  while  ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									static  const  char  * dest  =  " _attended@transfer/m " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * local_chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  cause ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * app  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-25 21:14:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_format_cap  * caps ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									caps  =  ao2_bump ( ast_channel_nativeformats ( chan1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									local_chan  =  ast_request ( " Local " ,  caps ,  NULL ,  chan1 ,  dest ,  & cause ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( caps ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! local_chan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												accountcode: Slightly change accountcode propagation.
The previous behavior was to simply set the accountcode of an outgoing
channel to the accountcode of the channel initiating the call.  It was
done this way a long time ago to allow the accountcode set on the SIP/100
channel to be propagated to a local channel so the dialplan execution on
the Local;2 channel would have the SIP/100 accountcode available.
SIP/100 -> Local;1/Local;2 -> SIP/200
Propagating the SIP/100 accountcode to the local channels is very useful.
Without any dialplan manipulation, all channels in this call would have
the same accountcode.
Using dialplan, you can set a different accountcode on the SIP/200 channel
either by setting the accountcode on the Local;2 channel or by the Dial
application's b(pre-dial), M(macro) or U(gosub) options, or by the
FollowMe application's b(pre-dial) option, or by the Queue application's
macro or gosub options.  Before Asterisk v12, the altered accountcode on
SIP/200 will remain until the local channels optimize out and the
accountcode would change to the SIP/100 accountcode.
Asterisk v1.8 attempted to add peeraccount support but ultimately had to
punt on the support.  The peeraccount support was rendered useless because
of how the CDR code needed to unconditionally force the caller's
accountcode onto the peer channel's accountcode.  The CEL events were thus
intentionally made to always use the channel's accountcode as the
peeraccount value.
With the arrival of Asterisk v12, the situation has improved somewhat so
peeraccount support can be made to work.  Using the indicated example, the
the accountcode values become as follows when the peeraccount is set on
SIP/100 before calling SIP/200:
SIP/100 ---> Local;1 ---- Local;2 ---> SIP/200
acct: 100 \/ acct: 200 \/ acct: 100 \/ acct: 200
peer: 200 /\ peer: 100 /\ peer: 200 /\ peer: 100
If a channel already has an accountcode it can only change by the
following explicit user actions:
1) A channel originate method that can specify an accountcode to use.
2) The calling channel propagating its non-empty peeraccount or its
non-empty accountcode if the peeraccount was empty to the outgoing
channel's accountcode before initiating the dial.  e.g., Dial and
FollowMe.  The exception to this propagation method is Queue.  Queue will
only propagate peeraccounts this way only if the outgoing channel does not
have an accountcode.
3) Dialplan using CHANNEL(accountcode).
4) Dialplan using CHANNEL(peeraccount) on the other end of a local
channel pair.
If a channel does not have an accountcode it can get one from the
following places:
1) The channel driver's configuration at channel creation.
2) Explicit user action as already indicated.
3) Entering a basic or stasis-mixing bridge from a peer channel's
peeraccount value.
You can specify the accountcode for an outgoing channel by setting the
CHANNEL(peeraccount) before using the Dial, FollowMe, and Queue
applications.  Queue adds the wrinkle that it will not overwrite an
existing accountcode on the outgoing channel with the calling channels
values.
Accountcode and peeraccount values propagate to an outgoing channel before
dialing.  Accountcodes also propagate when channels enter or leave a basic
or stasis-mixing bridge.  The peeraccount value only makes sense for
mixing bridges with two channels; it is meaningless otherwise.
* Made peeraccount functional by changing accountcode propagation as
described above.
* Fixed CEL extracting the wrong ie value for the peeraccount.  This was
done intentionally in Asterisk v1.8 when that version had to punt on
peeraccount.
* Fixed a few places dealing with accountcodes that were reading from
channels without the lock held.
AFS-65 #close
Review: https://reviewboard.asterisk.org/r/3601/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419520 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-24 22:48:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_lock_both ( local_chan ,  chan1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_req_accountcodes ( local_chan ,  chan1 ,  AST_CHANNEL_REQUESTOR_REPLACEMENT ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									pbx_builtin_setvar_helper ( local_chan ,  ATTENDEDTRANSFER ,  ast_channel_name ( chan1 ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												accountcode: Slightly change accountcode propagation.
The previous behavior was to simply set the accountcode of an outgoing
channel to the accountcode of the channel initiating the call.  It was
done this way a long time ago to allow the accountcode set on the SIP/100
channel to be propagated to a local channel so the dialplan execution on
the Local;2 channel would have the SIP/100 accountcode available.
SIP/100 -> Local;1/Local;2 -> SIP/200
Propagating the SIP/100 accountcode to the local channels is very useful.
Without any dialplan manipulation, all channels in this call would have
the same accountcode.
Using dialplan, you can set a different accountcode on the SIP/200 channel
either by setting the accountcode on the Local;2 channel or by the Dial
application's b(pre-dial), M(macro) or U(gosub) options, or by the
FollowMe application's b(pre-dial) option, or by the Queue application's
macro or gosub options.  Before Asterisk v12, the altered accountcode on
SIP/200 will remain until the local channels optimize out and the
accountcode would change to the SIP/100 accountcode.
Asterisk v1.8 attempted to add peeraccount support but ultimately had to
punt on the support.  The peeraccount support was rendered useless because
of how the CDR code needed to unconditionally force the caller's
accountcode onto the peer channel's accountcode.  The CEL events were thus
intentionally made to always use the channel's accountcode as the
peeraccount value.
With the arrival of Asterisk v12, the situation has improved somewhat so
peeraccount support can be made to work.  Using the indicated example, the
the accountcode values become as follows when the peeraccount is set on
SIP/100 before calling SIP/200:
SIP/100 ---> Local;1 ---- Local;2 ---> SIP/200
acct: 100 \/ acct: 200 \/ acct: 100 \/ acct: 200
peer: 200 /\ peer: 100 /\ peer: 200 /\ peer: 100
If a channel already has an accountcode it can only change by the
following explicit user actions:
1) A channel originate method that can specify an accountcode to use.
2) The calling channel propagating its non-empty peeraccount or its
non-empty accountcode if the peeraccount was empty to the outgoing
channel's accountcode before initiating the dial.  e.g., Dial and
FollowMe.  The exception to this propagation method is Queue.  Queue will
only propagate peeraccounts this way only if the outgoing channel does not
have an accountcode.
3) Dialplan using CHANNEL(accountcode).
4) Dialplan using CHANNEL(peeraccount) on the other end of a local
channel pair.
If a channel does not have an accountcode it can get one from the
following places:
1) The channel driver's configuration at channel creation.
2) Explicit user action as already indicated.
3) Entering a basic or stasis-mixing bridge from a peer channel's
peeraccount value.
You can specify the accountcode for an outgoing channel by setting the
CHANNEL(peeraccount) before using the Dial, FollowMe, and Queue
applications.  Queue adds the wrinkle that it will not overwrite an
existing accountcode on the outgoing channel with the calling channels
values.
Accountcode and peeraccount values propagate to an outgoing channel before
dialing.  Accountcodes also propagate when channels enter or leave a basic
or stasis-mixing bridge.  The peeraccount value only makes sense for
mixing bridges with two channels; it is meaningless otherwise.
* Made peeraccount functional by changing accountcode propagation as
described above.
* Fixed CEL extracting the wrong ie value for the peeraccount.  This was
done intentionally in Asterisk v1.8 when that version had to punt on
peeraccount.
* Fixed a few places dealing with accountcodes that were reading from
channels without the lock held.
AFS-65 #close
Review: https://reviewboard.asterisk.org/r/3601/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419520 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-07-24 22:48:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_unlock ( local_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge2 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  ast_local_setup_bridge ( local_chan ,  bridge2 ,  chan2 ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										app  =  ast_strdupa ( ast_channel_appl ( chan2 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  ast_local_setup_masquerade ( local_chan ,  chan2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_hangup ( local_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-07-08 14:56:10 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Since  bridges  need  to  be  unlocked  before  entering  ast_bridge_impart  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  core_local  may  call  into  it  then  the  bridges  need  to  be  unlocked  here . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge2 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_call ( local_chan ,  dest ,  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_hangup ( local_chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-08 14:56:10 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										BRIDGE_LOCK_ONE_OR_BOTH ( bridge1 ,  bridge2 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Get a ref for use later since this one is being stolen */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( local_chan ,  + 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-13 22:19:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_bridge_impart ( bridge1 ,  local_chan ,  chan1 ,  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_BRIDGE_IMPART_CHAN_INDEPENDENT ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_hangup ( local_chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_cleanup ( local_chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-08 14:56:10 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										BRIDGE_LOCK_ONE_OR_BOTH ( bridge1 ,  bridge2 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-08 14:56:10 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									BRIDGE_LOCK_ONE_OR_BOTH ( bridge1 ,  bridge2 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge2 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-20 16:05:08 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										void  * tech ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_channel  * locals [ 2 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-03-01 16:18:21 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Have to lock everything just in case a hangup comes in early */ 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-20 16:05:08 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_local_lock_all ( local_chan ,  & tech ,  & locals [ 0 ] ,  & locals [ 1 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-01 16:18:21 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! locals [ 0 ]  | |  ! locals [ 1 ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Transfer failed probably due to an early hangup -  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" missing other half of '%s' \n " ,  ast_channel_name ( local_chan ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-20 16:05:08 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_local_unlock_all ( tech ,  locals [ 0 ] ,  locals [ 1 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-01 16:18:21 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_cleanup ( local_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-03-01 16:18:21 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Make sure the peer is properly set */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( local_chan  ! =  locals [ 0 ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											SWAP ( locals [ 0 ] ,  locals [ 1 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_attended_transfer_message_add_link ( transfer_msg ,  locals ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-20 16:05:08 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_local_unlock_all ( tech ,  locals [ 0 ] ,  locals [ 1 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_attended_transfer_message_add_app ( transfer_msg ,  app ,  local_chan ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_cleanup ( local_chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  AST_BRIDGE_TRANSFER_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-05-22 15:52:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  ast_transfer_result  try_parking ( struct  ast_channel  * transferer ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * context ,  const  char  * exten ,  transfer_channel_cb  new_channel_cb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  transfer_channel_data  * user_data_wrapper ) 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_bridge_channel  * ,  transferer_bridge_channel ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 20:55:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-17 15:01:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_parking_provider_registered ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 20:55:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_lock ( transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 18:21:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									transferer_bridge_channel  =  ast_channel_get_bridge_channel ( transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_unlock ( transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 18:21:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! transferer_bridge_channel )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 20:55:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-17 15:01:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_parking_blind_transfer_park ( transferer_bridge_channel , 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-22 15:52:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										context ,  exten ,  new_channel_cb ,  user_data_wrapper ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 20:55:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 20:55:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  AST_BRIDGE_TRANSFER_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_bridge_set_transfer_variables ( struct  ast_channel  * chan ,  const  char  * value ,  int  attended )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * writevar ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * erasevar ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( attended )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writevar  =  ATTENDEDTRANSFER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										erasevar  =  BLINDTRANSFER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writevar  =  BLINDTRANSFER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										erasevar  =  ATTENDEDTRANSFER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pbx_builtin_setvar_helper ( chan ,  writevar ,  value ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-16 18:31:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									pbx_builtin_setvar_helper ( chan ,  erasevar ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Set  the  transfer  variable  as  appropriate  on  channels  involved  in  the  transfer 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  The  transferer  channel  will  have  its  variable  set  the  same  as  its  BRIDGEPEER 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  variable .  This  will  account  for  all  channels  that  it  is  bridged  to .  The  other  channels 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  involved  in  the  transfer  will  have  their  variable  set  to  the  transferer 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  channel ' s  name . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  transferer  The  channel  performing  the  transfer 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  channels  The  channels  belonging  to  the  bridge 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  is_attended  false   set  BLINDTRANSFER  and  unset  ATTENDEDTRANSFER 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *                     true    set  ATTENDEDTRANSFER  and  unset  BLINDTRANSFER 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  set_transfer_variables_all ( struct  ast_channel  * transferer ,  struct  ao2_container  * channels ,  int  is_attended )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ao2_iterator  iter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * transferer_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * transferer_bridgepeer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( transferer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									transferer_name  =  ast_strdupa ( ast_channel_name ( transferer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									transferer_bridgepeer  =  ast_strdupa ( S_OR ( pbx_builtin_getvar_helper ( transferer ,  " BRIDGEPEER " ) ,  " " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( transferer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( iter  =  ao2_iterator_init ( channels ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( chan  =  ao2_iterator_next ( & iter ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_cleanup ( chan ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( chan  = =  transferer )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_bridge_set_transfer_variables ( chan ,  transferer_bridgepeer ,  is_attended ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_bridge_set_transfer_variables ( chan ,  transferer_name ,  is_attended ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & iter ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 18:33:40 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_bridge  * ast_bridge_transfer_acquire_bridge ( struct  ast_channel  * chan )  
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge  =  ast_channel_get_bridge ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-09 14:27:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge  & &  ast_test_flag ( & bridge - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( AST_BRIDGE_FLAG_MASQUERADE_ONLY  |  AST_BRIDGE_FLAG_INVISIBLE ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_ref ( bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								enum  ast_transfer_result  ast_bridge_transfer_blind ( int  is_external ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_channel  * transferer ,  const  char  * exten ,  const  char  * context , 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										transfer_channel_cb  new_channel_cb ,  void  * user_data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_bridge  * ,  bridge ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_bridge_channel  * ,  bridge_channel ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ao2_container  * ,  channels ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 21:34:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_channel  * ,  transferee ,  NULL ,  ast_channel_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-22 15:52:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  transfer_channel_data  * ,  user_data_wrapper ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_blind_transfer_message  * ,  transfer_message ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  do_bridge_transfer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  transfer_prohibited ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_transfer_result  transfer_result ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									transfer_message  =  ast_blind_transfer_message_create ( is_external ,  transferer ,  exten ,  context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! transfer_message )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Out of memory. Not even possible to publish a Stasis message about the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Unable to allocate memory for blind transfer publication from %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_name ( transferer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 18:33:40 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge  =  ast_bridge_transfer_acquire_bridge ( transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										transfer_result  =  AST_BRIDGE_TRANSFER_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  publish ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									transfer_message - > bridge  =  ast_bridge_snapshot_create ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! transfer_message - > bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										transfer_result  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  publish ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									transferee  =  ast_bridge_peer ( bridge ,  transferer ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( transferee )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										transfer_message - > transferee  =  ast_channel_snapshot_get_latest ( ast_channel_uniqueid ( transferee ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! transfer_message - > transferee )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											transfer_result  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  publish ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-07 15:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_lock ( transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_channel  =  ast_channel_get_bridge_channel ( transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_unlock ( transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge_channel )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										transfer_result  =  AST_BRIDGE_TRANSFER_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  publish ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-05-22 15:52:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									user_data_wrapper  =  ao2_alloc ( sizeof ( * user_data_wrapper ) ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! user_data_wrapper )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										transfer_result  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  publish ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									user_data_wrapper - > data  =  user_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Take off hold if they are on hold. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_channel_write_unhold ( bridge_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-05-22 15:52:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									transfer_result  =  try_parking ( transferer ,  context ,  exten ,  new_channel_cb ,  user_data_wrapper ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 20:55:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( transfer_result  = =  AST_BRIDGE_TRANSFER_SUCCESS )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										goto  publish ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-05-22 15:52:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Since parking didn't take control of the user_data_wrapper, we are just going to raise the completed flag now. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									user_data_wrapper - > completed  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										SCOPED_LOCK ( lock ,  bridge ,  ast_bridge_lock ,  ast_bridge_unlock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 00:16:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										channels  =  ast_bridge_peers_nolock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! channels )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											transfer_result  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  publish ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ao2_container_count ( channels )  < =  1 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											transfer_result  =  AST_BRIDGE_TRANSFER_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  publish ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										transfer_prohibited  =  ast_test_flag ( & bridge - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_BRIDGE_FLAG_TRANSFER_PROHIBITED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										do_bridge_transfer  =  ast_test_flag ( & bridge - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ao2_container_count ( channels )  >  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( transfer_prohibited )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										transfer_result  =  AST_BRIDGE_TRANSFER_NOT_PERMITTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  publish ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									set_transfer_variables_all ( transferer ,  channels ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( do_bridge_transfer )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-20 13:06:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										transfer_result  =  blind_transfer_bridge ( is_external ,  transferer ,  bridge , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											exten ,  context ,  transferee ,  new_channel_cb ,  user_data_wrapper ,  transfer_message ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										goto  publish ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Reaching this portion means that we're dealing with a two-party bridge */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! transferee )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										transfer_result  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  publish ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge_channel_internal_queue_blind_transfer ( transferee ,  exten ,  context , 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-22 15:52:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												new_channel_cb ,  user_data_wrapper ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										transfer_result  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  publish ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_remove ( bridge ,  transferer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									transfer_result  =  AST_BRIDGE_TRANSFER_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								publish :  
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									transfer_message - > result  =  transfer_result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_publish_blind_transfer ( transfer_message ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  transfer_result ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Performs  an  attended  transfer  by  moving  a  channel  from  one  bridge  to  another 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  channel  that  is  bridged  to  the  source_channel  is  moved  into  the  dest_bridge  from 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  source_bridge_channel ' s  bridge .  The  swap_channel  is  swapped  out  of  the  dest_bridge  and  placed  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  source_bridge_channel ' s  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  dest_bridge  and  source_bridge_channel ' s  bridge  MUST  be  locked  before  calling  this  function . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  dest_bridge  The  final  bridge  for  the  attended  transfer 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-19 16:47:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  source_bridge_channel  Channel  who  is  bridged  to  the  channel  that  will  move 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  swap_channel  Channel  to  be  swapped  out  of  the  dest_bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  The  success  or  failure  of  the  swap  attempt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  enum  ast_transfer_result  bridge_swap_attended_transfer ( struct  ast_bridge  * dest_bridge ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_channel  * source_bridge_channel ,  struct  ast_channel  * swap_channel ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridged_to_source ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridged_to_source  =  ast_bridge_channel_peer ( source_bridge_channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 00:16:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridged_to_source 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  bridged_to_source - > state  = =  BRIDGE_CHANNEL_STATE_WAIT 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 00:16:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & bridged_to_source - > features - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridged_to_source - > swap  =  swap_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( bridge_do_move ( dest_bridge ,  bridged_to_source ,  1 ,  0 ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 00:16:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Must kick the source channel out of its bridge. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_channel_leave_bridge ( source_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE ,  AST_CAUSE_NORMAL_CLEARING ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 00:16:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Function  that  performs  an  attended  transfer  when  both  transferer  channels  are  bridged 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  method  by  which  the  transfer  is  performed  is  dependent  on  whether  the  bridges  allow  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  optimization  to  occur  between  them .  If  no  optimization  is  permitted ,  then  an  unreal  channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  is  placed  as  a  link  between  the  two  bridges .  If  optimization  is  permitted ,  then  that  means 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  we  are  free  to  perform  move  or  merge  operations  in  order  to  perform  the  transfer . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ note  to_transferee_bridge  and  to_target_bridge  MUST  be  locked  before  calling  this  function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  to_transferee  The  channel  that  is  bridged  to  the  transferee 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  to_transferee_bridge_channel  to_transferee ' s  bridge_channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  to_transfer_target  The  channel  that  is  bridged  to  the  transfer  target 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  to_target_bridge_channel  to_transfer_target ' s  bridge_channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  to_transferee_bridge  The  bridge  between  to_transferee  and  the  transferee 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  to_target_bridge  The  bridge  between  to_transfer_target  and  the  transfer_target 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-19 16:47:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  transfer_msg  Data  to  publish  for  a  stasis  attended  transfer  message 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ return  The  success  or  failure  of  the  attended  transfer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  enum  ast_transfer_result  two_bridge_attended_transfer ( struct  ast_channel  * to_transferee ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_channel  * to_transferee_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_channel  * to_transfer_target , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_channel  * to_target_bridge_channel , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_bridge  * to_transferee_bridge ,  struct  ast_bridge  * to_target_bridge , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_attended_transfer_message  * transfer_msg ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * kick_me [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											to_transferee_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											to_target_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_transfer_result  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * final_bridge  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ao2_container  * ,  channels ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									channels  =  ast_bridge_peers_nolock ( to_transferee_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! channels )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									set_transfer_variables_all ( to_transferee ,  channels ,  1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( ast_bridges_allow_optimization ( to_transferee_bridge ,  to_target_bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_BRIDGE_OPTIMIZE_SWAP_TO_CHAN_BRIDGE : 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										final_bridge  =  to_transferee_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  bridge_swap_attended_transfer ( to_transferee_bridge ,  to_target_bridge_channel ,  to_transferee ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_OPTIMIZE_SWAP_TO_PEER_BRIDGE : 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										final_bridge  =  to_target_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  bridge_swap_attended_transfer ( to_target_bridge ,  to_transferee_bridge_channel ,  to_transfer_target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_OPTIMIZE_MERGE_TO_CHAN_BRIDGE : 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										final_bridge  =  to_transferee_bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_do_merge ( to_transferee_bridge ,  to_target_bridge ,  kick_me ,  ARRAY_LEN ( kick_me ) ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  AST_BRIDGE_TRANSFER_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_OPTIMIZE_MERGE_TO_PEER_BRIDGE : 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										final_bridge  =  to_target_bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-24 15:38:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge_do_merge ( to_target_bridge ,  to_transferee_bridge ,  kick_me ,  ARRAY_LEN ( kick_me ) ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  AST_BRIDGE_TRANSFER_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_BRIDGE_OPTIMIZE_PROHIBITED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Just because optimization wasn't doable doesn't necessarily mean
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  that  we  can  actually  perform  the  transfer .  Some  reasons  for  non - optimization 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  indicate  bridge  invalidity ,  so  let ' s  check  those  before  proceeding . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( to_transferee_bridge - > inhibit_merge  | |  to_transferee_bridge - > dissolved  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												to_target_bridge - > inhibit_merge  | |  to_target_bridge - > dissolved )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  AST_BRIDGE_TRANSFER_INVALID ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  attended_transfer_bridge ( to_transferee ,  to_transfer_target , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											to_transferee_bridge ,  to_target_bridge ,  transfer_msg ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								end :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res  = =  AST_BRIDGE_TRANSFER_SUCCESS )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_attended_transfer_message_add_merge ( transfer_msg ,  final_bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								enum  ast_transfer_result  ast_bridge_transfer_attended ( struct  ast_channel  * to_transferee ,  
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_channel  * to_transfer_target ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_bridge  * ,  to_transferee_bridge ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_bridge  * ,  to_target_bridge ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_bridge_channel  * ,  to_transferee_bridge_channel ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_bridge_channel  * ,  to_target_bridge_channel ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ao2_container  * ,  channels ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_channel  * ,  transferee ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_attended_transfer_message  * ,  transfer_msg ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-04-11 12:43:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge  * the_bridge  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_channel  * chan_bridged ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel  * chan_unbridged ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  transfer_prohibited ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  do_bridge_transfer ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  ast_transfer_result  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * app  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-22 15:11:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  hangup_target  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 18:33:40 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									to_transferee_bridge  =  ast_bridge_transfer_acquire_bridge ( to_transferee ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									to_target_bridge  =  ast_bridge_transfer_acquire_bridge ( to_transfer_target ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									transfer_msg  =  ast_attended_transfer_message_create ( 1 ,  to_transferee ,  to_transferee_bridge , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											to_transfer_target ,  to_target_bridge ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! transfer_msg )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Unable to create Stasis publication for attended transfer from %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_channel_name ( to_transferee ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* They can't both be unbridged, you silly goose! */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! to_transferee_bridge  & &  ! to_target_bridge )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  AST_BRIDGE_TRANSFER_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_channel_lock ( to_transferee ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									to_transferee_bridge_channel  =  ast_channel_get_bridge_channel ( to_transferee ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( to_transferee ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_lock ( to_transfer_target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									to_target_bridge_channel  =  ast_channel_get_bridge_channel ( to_transfer_target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_channel_unlock ( to_transfer_target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( to_transferee_bridge_channel )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Take off hold if they are on hold. */ 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-31 11:14:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ast_bridge_channel_write_unhold ( to_transferee_bridge_channel ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Transferee channel disappeared during transfer! \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  end ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( to_target_bridge_channel )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										const  char  * target_complete_sound ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Take off hold if they are on hold. */ 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-31 11:14:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ast_bridge_channel_write_unhold ( to_target_bridge_channel ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Target channel disappeared during transfer! \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  end ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-06 22:46:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Is there a courtesy sound to play to the target? */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_lock ( to_transfer_target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										target_complete_sound  =  pbx_builtin_getvar_helper ( to_transfer_target , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" ATTENDED_TRANSFER_COMPLETE_SOUND " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ast_strlen_zero ( target_complete_sound ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											target_complete_sound  =  ast_strdupa ( target_complete_sound ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											target_complete_sound  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unlock ( to_transfer_target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! target_complete_sound )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_lock ( to_transferee ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											target_complete_sound  =  pbx_builtin_getvar_helper ( to_transferee , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" ATTENDED_TRANSFER_COMPLETE_SOUND " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! ast_strlen_zero ( target_complete_sound ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												target_complete_sound  =  ast_strdupa ( target_complete_sound ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												target_complete_sound  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_unlock ( to_transferee ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( target_complete_sound )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_channel_write_playfile ( to_target_bridge_channel ,  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												target_complete_sound ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Let's get the easy one out of the way first */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( to_transferee_bridge  & &  to_target_bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! to_transferee_bridge_channel  | |  ! to_target_bridge_channel )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  AST_BRIDGE_TRANSFER_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-31 15:34:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_lock_both ( to_transferee_bridge ,  to_target_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  two_bridge_attended_transfer ( to_transferee ,  to_transferee_bridge_channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												to_transfer_target ,  to_target_bridge_channel , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												to_transferee_bridge ,  to_target_bridge ,  transfer_msg ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( to_transferee_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_unlock ( to_target_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-06-22 15:11:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										hangup_target  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									the_bridge  =  to_transferee_bridge  ? :  to_target_bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chan_bridged  =  to_transferee_bridge  ?  to_transferee  :  to_transfer_target ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									chan_unbridged  =  to_transferee_bridge  ?  to_transfer_target  :  to_transferee ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-04-16 10:51:50 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Race  condition  makes  it  possible  for  app  to  be  NULL ,  so  get  the  app  prior  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  transferring  with  a  fallback  of  " unknown " . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									app  =  ast_strdupa ( ast_channel_appl ( chan_unbridged )  ? :  " unknown " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  chan_count ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										SCOPED_LOCK ( lock ,  the_bridge ,  ast_bridge_lock ,  ast_bridge_unlock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										channels  =  ast_bridge_peers_nolock ( the_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! channels )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chan_count  =  ao2_container_count ( channels ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( chan_count  < =  1 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  =  AST_BRIDGE_TRANSFER_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										transfer_prohibited  =  ast_test_flag ( & the_bridge - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_BRIDGE_FLAG_TRANSFER_PROHIBITED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										do_bridge_transfer  =  ast_test_flag ( & the_bridge - > feature_flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												chan_count  >  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( transfer_prohibited )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  AST_BRIDGE_TRANSFER_NOT_PERMITTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-12-13 20:13:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									set_transfer_variables_all ( to_transferee ,  channels ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( do_bridge_transfer )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-22 15:11:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Hang  up  the  target  if  it  was  bridged .  Note ,  if  it  is  not  bridged 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  it  is  hung  up  during  the  masquerade . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hangup_target  =  chan_bridged  = =  to_transfer_target ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-04-11 12:43:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_lock ( the_bridge ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  attended_transfer_bridge ( chan_bridged ,  chan_unbridged ,  the_bridge ,  NULL ,  transfer_msg ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-04-11 12:43:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_unlock ( the_bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									transferee  =  get_transferee ( channels ,  chan_bridged ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! transferee )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:20:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( bridge_channel_internal_queue_attended_transfer ( transferee ,  chan_unbridged ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res  =  AST_BRIDGE_TRANSFER_FAIL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-28 14:45:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_remove ( the_bridge ,  chan_bridged ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_attended_transfer_message_add_app ( transfer_msg ,  app ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-19 14:54:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									res  =  AST_BRIDGE_TRANSFER_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								end :  
						 
					
						
							
								
									
										
										
										
											2017-06-20 16:01:48 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ( res  = =  AST_BRIDGE_TRANSFER_SUCCESS  & &  hangup_target )  | |  res  = =  AST_BRIDGE_TRANSFER_FAIL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-22 15:11:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_softhangup ( to_transfer_target ,  AST_SOFTHANGUP_DEV ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix race condition that could result in ARI transfer messages not being sent.
From reviewboard:
"During blind transfer testing, it was noticed that tests were failing
occasionally because the ARI blind transfer event was not being sent.
After investigating, I detected a race condition in the blind transfer
code. When blind transferring a single channel, the actual transfer
operation (i.e. removing the transferee from the bridge and directing
them to the proper dialplan location) is queued onto the transferee
bridge channel. After queuing the transfer operation, the blind transfer
Stasis message is published. At the time of publication, snapshots of
the channels and bridge involved are created. The ARI subscriber to the
blind transfer Stasis message then attempts to determine if the bridge
or any of the involved channels are subscribed to by ARI applications.
If so, then the blind transfer message is sent to the applications. The
way that the ARI blind transfer message handler works is to first see
if the transferer channel is subscribed to. If not, then iterate over
all the channel IDs in the bridge snapshot and determine if any of
those are subscribed to. In the test we were running, the lone
transferee channel was subscribed to, so an ARI event should have been
sent to our application. Occasionally, though, the bridge snapshot did
not have any channels IDs on it at all. Why?
The problem is that since the blind transfer operation is handled by a
separate thread, it is possible that the transfer will have completed and
the channels removed from the bridge before we publish the blind transfer
Stasis message. Since the blind transfer has completed, the bridge on
which the transfer occurred no longer has any channels on it, so the
resulting bridge snapshot has no channels on it. Through investigation of
the code, I found that attended transfers can have this issue too for the
case where a transferee is transferred to an application."
The fix employed here is to decouple the creation of snapshots for the transfer
messages from the publication of the transfer messages. This way, snapshots
can be created to reflect what they are at the time of the transfer operation.
Review: https://reviewboard.asterisk.org/r/4135
........
Merged revisions 427848 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 427870 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427873 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-11-14 15:28:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									transfer_msg - > result  =  res ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_publish_attended_transfer ( transfer_msg ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 18:42:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  res ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Service  the  bridge  manager  request . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  requesting  service . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_manager_service ( struct  ast_bridge  * bridge )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( bridge - > callid )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_callid_threadassoc_change ( bridge - > callid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Do any pending bridge actions. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_handle_actions ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Bridge  manager  service  thread . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * bridge_manager_thread ( void  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_manager_controller  * manager  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_manager_request  * request ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_lock ( manager ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ! manager - > stop )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										request  =  AST_LIST_REMOVE_HEAD ( & manager - > service_requests ,  node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! request )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cond_wait ( & manager - > cond ,  ao2_object_get_lockaddr ( manager ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlock ( manager ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Service the bridge. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_manager_service ( request - > bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( request - > bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( request ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_lock ( manager ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( manager ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Destroy  the  bridge  manager  controller . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj  Bridge  manager  to  destroy . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_manager_destroy ( void  * obj )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  bridge_manager_controller  * manager  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_manager_request  * request ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( manager - > thread  ! =  AST_PTHREADT_NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Stop the manager thread. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_lock ( manager ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										manager - > stop  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cond_signal ( & manager - > cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlock ( manager ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Waiting for bridge manager thread to die. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pthread_join ( manager - > thread ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Destroy the service request queue. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( request  =  AST_LIST_REMOVE_HEAD ( & manager - > service_requests ,  node ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( request - > bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( request ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cond_destroy ( & manager - > cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Create  the  bridge  manager  controller . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-19 16:47:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ return  manager  on  success . 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ retval  NULL  on  error . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  bridge_manager_controller  * bridge_manager_create ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_manager_controller  * manager ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									manager  =  ao2_alloc ( sizeof ( * manager ) ,  bridge_manager_destroy ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! manager )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Well. This isn't good. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_init ( & manager - > cond ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_HEAD_INIT_NOLOCK ( & manager - > service_requests ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Create the bridge manager thread. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_pthread_create ( & manager - > thread ,  NULL ,  bridge_manager_thread ,  manager ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Well. This isn't good either. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										manager - > thread  =  AST_PTHREADT_NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( manager ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										manager  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  manager ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Bridge  ao2  container  sort  function . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj_left  pointer  to  the  ( user - defined  part )  of  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  obj_right  pointer  to  the  ( user - defined  part )  of  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  flags  flags  from  ao2_callback ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *    OBJ_POINTER  -  if  set ,  ' obj_right ' ,  is  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *    OBJ_KEY  -  if  set ,  ' obj_right ' ,  is  a  search  key  item  that  is  not  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *    OBJ_PARTIAL_KEY  -  if  set ,  ' obj_right ' ,  is  a  partial  search  key  item  that  is  not  an  object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  < 0  if  obj_left  <  obj_right 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  = 0  if  obj_left  = =  obj_right 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  > 0  if  obj_left  >  obj_right 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_sort_cmp ( const  void  * obj_left ,  const  void  * obj_right ,  int  flags )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  struct  ast_bridge  * bridge_left  =  obj_left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  struct  ast_bridge  * bridge_right  =  obj_right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * right_key  =  obj_right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  cmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( flags  &  ( OBJ_POINTER  |  OBJ_KEY  |  OBJ_PARTIAL_KEY ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_POINTER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										right_key  =  bridge_right - > uniqueid ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Fall through */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cmp  =  strcmp ( bridge_left - > uniqueid ,  right_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_PARTIAL_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cmp  =  strncmp ( bridge_left - > uniqueid ,  right_key ,  strlen ( right_key ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cmp ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_bridge  * ast_bridge_find_by_id ( const  char  * bridge_id )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ao2_find ( bridges ,  bridge_id ,  OBJ_SEARCH_KEY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  complete_bridge_live_search ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:42:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge  =  obj ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:42:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_cli_completion_add ( ast_strdup ( bridge - > uniqueid ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CMP_STOP ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:42:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:42:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * complete_bridge_live ( const  char  * word )  
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:42:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_callback ( bridges ,  ast_strlen_zero ( word )  ?  0  :  OBJ_PARTIAL_KEY , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										complete_bridge_live_search ,  ( char  * )  word ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:42:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:42:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * handle_bridge_show_all ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define FORMAT_HDR "%-36s %-36s %5s %-15s %-15s %s\n" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define FORMAT_ROW "%-36s %-36s %5u %-15s %-15s %s\n" 
  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_iterator  iter ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " bridge show all " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" Usage: bridge show all \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"        List all bridges \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  FORMAT_HDR ,  " Bridge-ID " ,  " Name " ,  " Chans " ,  " Type " ,  " Technology " ,  " Duration " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 19:19:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									iter  =  ao2_iterator_init ( bridges ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( ;  ( bridge  =  ao2_iterator_next ( & iter ) ) ;  ao2_ref ( bridge ,  - 1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_snapshot  * snapshot  =  ast_bridge_get_snapshot ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:32:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										char  print_time [ 32 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( snapshot )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-29 03:03:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_format_duration_hh_mm_ss ( ast_tvnow ( ) . tv_sec  -  snapshot - > creationtime . tv_sec ,  print_time ,  sizeof ( print_time ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  FORMAT_ROW , 
							 
						 
					
						
							
								
									
										
											 
										
											
												bridging: Fix multiple bridging issues causing SEGVs and FRACKs.
Issues:
* The bridging core allowed multiple bridges to be created with the same
  unique bridgeId at the same time.  Only the last bridge created with the
  duplicate name was actually saved to the core bridges container.
* The bridging core was creating a stasis topic for the bridge and saving it
  in the bridge->topic field but not increasing its reference count.  In the
  case where two bridges were created with the same uniqueid (which is also
  the topic name), the second bridge would get the _existing_ topic the first
  bridge created.  When the first bridge was destroyed, it would take the
  topic with it so when the second bridge attempted to publish a message to
  it it either FRACKed or SEGVd.
* The bridge destructor, which also destroys the bridge topic, is run from the
  bridge manager thread not the caller's thread.  This makes it possible for
  an ARI developer to create a new one with the same uniqueid believing the
  old one was destroyed when, in fact, the old one's destructor hadn't
  completed. This could cause the new bridge to get the old one's topic just
  before the topic was destroyed.  When the new bridge attempted to publish
  a message on that topic, asterisk could either FRACK or SEGV.
* The ARI bridges resource also allowed multiple bridges to be created with
  the same uniqueid but it kept the duplicate bridges in its app_bridges
  container.  This created a situation where if you added two bridges with
  the same "bridge1" uniqueid, all operations on "bridge1" were performed on
  the first bridge created and the second was basically orphaned.  If you
  attempted to delete what you thought was the second bridge, you actually
  deleted the first one created.
Changes:
* A new API `ast_bridge_topic_exists(uniqueid)` was created to determine if
  a topic already exists for a bridge.
* `bridge_base_init()` in bridge.c and `ast_ari_bridges_create()` in
  resource_bridges.c now call `ast_bridge_topic_exists(uniqueid)` to check
  if a bridge with the requested uniqueid already exists and will fail if it
  does.
* `bridge_register()` in bridges.c now checks the core bridges container to
  make sure a bridge doesn't already exist with the requested uniqueid.
  Although most callers of `bridge_register()` will have already called
  `bridge_base_init()`, which will now fail on duplicate bridges, there
  is no guarantee of this so we must check again.
* The core bridges container allocation was changed to reject duplicate
  uniqueids instead of silently replacing an existing one. This is a "belt
  and suspenders" check.
* A global mutex was added to bridge.c to prevent concurrent calls to
  `bridge_base_init()` and `bridge_register()`.
* Even though you can no longer create multiple bridges with the same uniqueid
  at the same time, it's still possible that the bridge topic might be
  destroyed while a second bridge with the same uniqueid was trying to use
  it. To address this, the bridging core now increments the reference count
  on bridge->topic when a bridge is created and decrements it when the
  bridge is destroyed.
* `bridge_create_common()` in res_stasis.c now checks the stasis app_bridges
  container to make sure a bridge with the requested uniqueid doesn't already
  exist.  This may seem like overkill but there are so many entrypoints to
  bridge creation that we need to be safe and catch issues as soon in the
  process as possible.
* The stasis app_bridges container allocation was changed to reject duplicate
  uniqueids instead of adding them. This is a "belt and suspenders" check.
* The `bridge show all` CLI command now shows the bridge name as well as the
  bridge id.
* Response code 409 "Conflict" was added as a possible response from the ARI
  bridge create resources to signal that a bridge with the requested uniqueid
  already exists.
* Additional debugging was added to multiple bridging and stasis files.
Resolves: #211
											 
										 
										
											2025-01-22 13:52:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												bridge - > uniqueid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												S_OR ( bridge - > name ,  " <unknown> " ) , 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												snapshot - > num_channels , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												S_OR ( snapshot - > subclass ,  " <unknown> " ) , 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:32:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												S_OR ( snapshot - > technology ,  " <unknown> " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												print_time ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_ref ( snapshot ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & iter ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# undef FORMAT_HDR 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef FORMAT_ROW 
  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 19:19:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Internal callback function for sending channels in a bridge to the CLI */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_show_specific_print_channel ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * uniqueid  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_cli_args  * a  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * snapshot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-10 11:28:18 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									snapshot  =  ast_channel_snapshot_get_latest ( uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! snapshot )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 19:19:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-07 13:18:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Channel: %s \n " ,  snapshot - > base - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-10 11:28:18 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_ref ( snapshot ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 19:19:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * handle_bridge_show_specific ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-07-08 19:19:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_snapshot  * snapshot ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:32:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  print_time [ 32 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " bridge show " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" Usage: bridge show <bridge-id> \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"        Show information about the <bridge-id> bridge \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  2 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  complete_bridge_live ( a - > word ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( a - > argc  ! =  3 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									snapshot  =  ast_bridge_get_snapshot_by_uniqueid ( a - > argv [ 2 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! snapshot )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Bridge '%s' not found \n " ,  a - > argv [ 2 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:32:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_format_duration_hh_mm_ss ( ast_tvnow ( ) . tv_sec  -  snapshot - > creationtime . tv_sec ,  print_time ,  sizeof ( print_time ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 19:19:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Id: %s \n " ,  snapshot - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Type: %s \n " ,  S_OR ( snapshot - > subclass ,  " <unknown> " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Technology: %s \n " ,  S_OR ( snapshot - > technology ,  " <unknown> " ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:32:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Subclass: %s \n " ,  snapshot - > subclass ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Creator: %s \n " ,  snapshot - > creator ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Name: %s \n " ,  snapshot - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-11 01:14:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Video-Mode: %s \n " ,  ast_bridge_video_mode_to_string ( snapshot - > video_mode ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:32:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Video-Source-Id: %s \n " ,  snapshot - > video_source_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 19:19:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Num-Channels: %u \n " ,  snapshot - > num_channels ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 22:32:18 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Num-Active: %u \n " ,  snapshot - > num_active ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Duration: %s \n " ,  print_time ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-08 19:19:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_callback ( snapshot - > channels ,  OBJ_NODATA ,  bridge_show_specific_print_channel ,  a ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-19 13:34:41 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_ref ( snapshot ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifdef AST_DEVMODE 
  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * handle_bridge_destroy_specific ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " bridge destroy " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" Usage: bridge destroy <bridge-id> \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"        Destroy the <bridge-id> bridge \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  2 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  complete_bridge_live ( a - > word ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( a - > argc  ! =  3 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge  =  ast_bridge_find_by_id ( a - > argv [ 2 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Bridge '%s' not found \n " ,  a - > argv [ 2 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Destroying bridge '%s' \n " ,  a - > argv [ 2 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-22 21:09:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_destroy ( bridge ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * complete_bridge_participant ( const  char  * bridge_name ,  const  char  * word )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  wordlen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge  =  ast_bridge_find_by_id ( bridge_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-01-09 22:56:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									wordlen  =  strlen ( word ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strncasecmp ( ast_channel_name ( bridge_channel - > chan ) ,  word ,  wordlen ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ast_cli_completion_add ( ast_strdup ( ast_channel_name ( bridge_channel - > chan ) ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_ref ( bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * handle_bridge_kick_channel ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2017-02-11 10:57:03 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									static  const  char  *  const  completions [ ]  =  {  " all " ,  NULL  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " bridge kick " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" Usage: bridge kick <bridge-id> <channel-name | all> \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"        Kick the <channel-name> channel out of the <bridge-id> bridge \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"        If all is specified as the channel name then all channels will be \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"        kicked out of the bridge. \n " ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  2 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  complete_bridge_live ( a - > word ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  3 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_cli_complete ( a - > word ,  completions ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  complete_bridge_participant ( a - > argv [ 2 ] ,  a - > word ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( a - > argc  ! =  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge  =  ast_bridge_find_by_id ( a - > argv [ 2 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Bridge '%s' not found \n " ,  a - > argv [ 2 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! strcasecmp ( a - > argv [ 3 ] ,  " all " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_channel  * bridge_channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Kicking all channels from bridge '%s' \n " ,  a - > argv [ 2 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_bridge_lock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_TRAVERSE ( & bridge - > channels ,  bridge_channel ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_bridge_channel_queue_callback ( bridge_channel ,  0 ,  kick_it ,  NULL ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_unlock ( bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_channel  * chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										chan  =  ast_channel_get_by_name_prefix ( a - > argv [ 3 ] ,  strlen ( a - > argv [ 3 ] ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! chan )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  " Channel '%s' not found \n " ,  a - > argv [ 3 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Kicking channel '%s' from bridge '%s' \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_channel_name ( chan ) ,  a - > argv [ 2 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_bridge_kick ( bridge ,  chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_channel_unref ( chan ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( bridge ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! Bridge technology capabilities to string. */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  const  char  * tech_capability2str ( uint32_t  capabilities )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( capabilities  &  AST_BRIDGE_CAPABILITY_HOLDING )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										type  =  " Holding " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( capabilities  &  AST_BRIDGE_CAPABILITY_EARLY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										type  =  " Early " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( capabilities  &  AST_BRIDGE_CAPABILITY_NATIVE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										type  =  " Native " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( capabilities  &  AST_BRIDGE_CAPABILITY_1TO1MIX )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										type  =  " 1to1Mix " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( capabilities  &  AST_BRIDGE_CAPABILITY_MULTIMIX )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										type  =  " MultiMix " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										type  =  " <Unknown> " ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  type ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * handle_bridge_technology_show ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define FORMAT_HDR "%-20s %-20s %8s %s\n" 
  
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define FORMAT_ROW "%-20s %-20s %8u %s\n" 
  
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * cur ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " bridge technology show " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" Usage: bridge technology show \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"        List registered bridge technologies \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  FORMAT_HDR ,  " Name " ,  " Type " ,  " Priority " ,  " Suspended " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_RDLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( & bridge_technologies ,  cur ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  char  * type ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-03-05 18:18:27 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Decode type for display */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										type  =  tech_capability2str ( cur - > capabilities ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  FORMAT_ROW ,  cur - > name ,  type ,  cur - > preference , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_CLI_YESNO ( cur - > suspended ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef FORMAT 
  
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * complete_bridge_technology ( const  char  * word )  
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * cur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  wordlen ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									wordlen  =  strlen ( word ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_RDLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( & bridge_technologies ,  cur ,  entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! strncasecmp ( cur - > name ,  word ,  wordlen ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ast_cli_completion_add ( ast_strdup ( cur - > name ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-04-21 18:11:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * handle_bridge_technology_suspend ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * cur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  suspend ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  successful ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " bridge technology {suspend|unsuspend} " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" Usage: bridge technology {suspend|unsuspend} <technology-name> \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"        Suspend or unsuspend a bridge technology. \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( a - > pos  = =  3 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-17 05:31:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  complete_bridge_technology ( a - > word ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( a - > argc  ! =  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									suspend  =  ! strcasecmp ( a - > argv [ 2 ] ,  " suspend " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									successful  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_WRLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( & bridge_technologies ,  cur ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( cur - > name ,  a - > argv [ 3 ] ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											successful  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( suspend )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_bridge_technology_suspend ( cur ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_bridge_technology_unsuspend ( cur ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( successful )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( suspend )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  " Suspended bridge technology '%s' \n " ,  a - > argv [ 3 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  " Unsuspended bridge technology '%s' \n " ,  a - > argv [ 3 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-07-11 18:44:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Bridge technology '%s' not found \n " ,  a - > argv [ 3 ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  ast_cli_entry  bridge_cli [ ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_bridge_show_all ,  " List all bridges " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_bridge_show_specific ,  " Show information about a bridge " ) , 
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifdef AST_DEVMODE 
  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_bridge_destroy_specific ,  " Destroy a bridge " ) , 
							 
						 
					
						
							
								
									
										
										
										
											2014-07-25 10:49:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_bridge_kick_channel ,  " Kick a channel from a bridge " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_bridge_technology_show ,  " List registered bridge technologies " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_bridge_technology_suspend ,  " Suspend/unsuspend a bridge technology " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  handle_manager_bridge_tech_suspend ( struct  mansession  * s ,  const  struct  message  * m ,  int  suspend )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * name  =  astman_get_header ( m ,  " BridgeTechnology " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * cur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  successful  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " BridgeTechnology must be provided " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_RDLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( & bridge_technologies ,  cur ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( cur - > name ,  name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											successful  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( suspend )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_bridge_technology_suspend ( cur ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_bridge_technology_unsuspend ( cur ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! successful )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " BridgeTechnology not found " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									astman_send_ack ( s ,  m ,  ( suspend  ?  " Suspended bridge technology "  :  " Unsuspended bridge technology " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  manager_bridge_tech_suspend ( struct  mansession  * s ,  const  struct  message  * m )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  handle_manager_bridge_tech_suspend ( s ,  m ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  manager_bridge_tech_unsuspend ( struct  mansession  * s ,  const  struct  message  * m )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  handle_manager_bridge_tech_suspend ( s ,  m ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  manager_bridge_tech_list ( struct  mansession  * s ,  const  struct  message  * m )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * id  =  astman_get_header ( m ,  " ActionID " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  ast_str  * ,  id_text ,  ast_str_create ( 128 ) ,  ast_free ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_technology  * cur ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 18:16:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  num_items  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! id_text )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_send_error ( s ,  m ,  " Internal error " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_strlen_zero ( id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_str_set ( & id_text ,  0 ,  " ActionID: %s \r \n " ,  id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-12 18:09:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									astman_send_listack ( s ,  m ,  " Bridge technology listing will follow " ,  " start " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_RDLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( & bridge_technologies ,  cur ,  entry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  char  * type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										type  =  tech_capability2str ( cur - > capabilities ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										astman_append ( s , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" Event: BridgeTechnologyListItem \r \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" BridgeTechnology: %s \r \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" BridgeType: %s \r \n " 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" BridgePriority: %u \r \n " 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" BridgeSuspended: %s \r \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" %s " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" \r \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cur - > name ,  type ,  cur - > preference ,  AST_YESNO ( cur - > suspended ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_str_buffer ( id_text ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 18:16:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										+ + num_items ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & bridge_technologies ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-09 18:16:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									astman_send_list_complete_start ( s ,  m ,  " BridgeTechnologyListComplete " ,  num_items ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									astman_send_list_complete_end ( s ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:36:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Print  bridge  object  key  ( name ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  12.0 .0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  v_obj  A  pointer  to  the  object  we  want  the  key  printed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  where  User  data  needed  by  prnt  to  determine  where  to  put  output . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  prnt  Print  output  callback  function  to  use . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_prnt_obj ( void  * v_obj ,  void  * where ,  ao2_prnt_fn  * prnt )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge  * bridge  =  v_obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									prnt ( where ,  " %s %s chans:%u " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:36:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bridge - > uniqueid ,  bridge - > v_table - > name ,  bridge - > num_channels ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2015-03-26 22:24:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Shutdown  the  bridging  system .   Stuff  to  do  on  graceful  shutdown . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ since  13.3 .0 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2015-03-26 22:24:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  bridge_cleanup ( void )  
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_manager_unregister ( " BridgeTechnologyList " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_manager_unregister ( " BridgeTechnologySuspend " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_manager_unregister ( " BridgeTechnologyUnsuspend " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli_unregister_multiple ( bridge_cli ,  ARRAY_LEN ( bridge_cli ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:36:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_container_unregister ( " bridges " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:39:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_cleanup ( bridges ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridges  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( bridge_manager ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_manager  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_bridging_init ( void )  
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2015-02-11 17:39:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_register_cleanup ( bridge_cleanup ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-05-30 17:05:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_stasis_bridging_init ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridge_manager  =  bridge_manager_create ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridge_manager )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-07-11 18:44:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bridges  =  ao2_container_alloc_rbtree ( AO2_ALLOC_OPT_LOCK_MUTEX , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE ,  bridge_sort_cmp ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridges )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-12 23:36:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_container_register ( " bridges " ,  bridges ,  bridge_prnt_obj ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_bridging_init_basic ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-07-11 18:44:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli_register_multiple ( bridge_cli ,  ARRAY_LEN ( bridge_cli ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-11-01 21:51:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_manager_register_xml_core ( " BridgeTechnologyList " ,  0 ,  manager_bridge_tech_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_manager_register_xml_core ( " BridgeTechnologySuspend " ,  0 ,  manager_bridge_tech_suspend ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_manager_register_xml_core ( " BridgeTechnologyUnsuspend " ,  0 ,  manager_bridge_tech_unsuspend ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-05-21 18:00:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-30 20:33:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}