2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
									
										
										
										
											2005-09-14 20:46:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Asterisk  - -  An  open  source  telephony  toolkit . 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-10 20:40:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  ( C )  1999  -  2006 ,  Digium ,  Inc . 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2004-09-10 13:40:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Mark  Spencer  < markster @ digium . com > 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2005-09-14 20:46:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  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 . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 *  This  program  is  free  software ,  distributed  under  the  terms  of 
							 
						 
					
						
							
								
									
										
										
										
											2005-09-14 20:46:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  the  GNU  General  Public  License  Version  2.  See  the  LICENSE  file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  at  the  top  of  the  source  tree . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-10-24 20:12:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \file
  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Call  Detail  Record  API 
							 
						 
					
						
							
								
									
										
										
										
											2005-12-30 21:18:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ author  Mark  Spencer  < markster @ digium . com > 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2006-01-04 12:11:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ note  Includes  code  and  algorithms  from  the  Zapata  library . 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-14 19:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ note  We  do  a  lot  of  checking  here  in  the  CDR  code  to  try  to  be  sure  we  don ' t  ever  let  a  CDR  slip 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  through  our  fingers  somehow .   If  someone  allocates  a  CDR ,  it  must  be  completely  handled  normally 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  or  a  WARNING  shall  be  logged ,  so  that  we  can  best  keep  track  of  any  escape  condition  where  the  CDR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  isn ' t  properly  generated  and  posted . 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-10-18 14:17:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \li \ref cdr.c uses the configuration file \ref cdr.conf
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ addtogroup  configuration_file  Configuration  Files 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ page  cdr . conf  cdr . conf 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ verbinclude  cdr . conf . sample 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-14 19:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-06-15 16:20:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*** MODULEINFO
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< support_level > core < / support_level > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-07 18:54:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <signal.h> 
  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <inttypes.h> 
  
						 
					
						
							
								
									
										
										
										
											2005-04-22 13:11:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-21 06:02:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/lock.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/channel.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/cdr.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/callerid.h" 
  
						 
					
						
							
								
									
										
										
										
											2007-12-06 15:12:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/manager.h" 
  
						 
					
						
							
								
									
										
										
										
											2005-04-21 06:02:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/causes.h" 
  
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/linkedlists.h" 
  
						 
					
						
							
								
									
										
										
										
											2005-04-21 06:02:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/utils.h" 
  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/sched.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/config.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/cli.h" 
  
						 
					
						
							
								
									
										
										
										
											2006-02-01 23:05:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/stringfields.h" 
  
						 
					
						
							
								
									
										
										
										
											2010-07-08 14:48:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/data.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/config_options.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/json.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/parking.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/stasis.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/stasis_channels.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-07-25 04:18:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/stasis_bridges.h" 
  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/stasis_message_router.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "asterisk/astobj2.h" 
  
						 
					
						
							
								
									
										
										
										
											2016-06-03 11:35:49 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  "asterisk/taskprocessor.h" 
  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-07-11 02:06:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*** DOCUMENTATION
  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									< configInfo  name = " cdr "  language = " en_US " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< synopsis > Call  Detail  Record  configuration < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< para > CDR  is  Call  Detail  Record ,  which  provides  logging  services  via  a  variety  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pluggable  backend  modules .  Detailed  call  information  can  be  recorded  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											databases ,  files ,  etc .  Useful  for  billing ,  fraud  prevention ,  compliance  with 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Sarbanes - Oxley  aka  The  Enron  Act ,  QOS  evaluations ,  and  more . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< configFile  name = " cdr.conf " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< configObject  name = " general " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< synopsis > Global  settings  applied  to  the  CDR  engine . < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " debug " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< synopsis > Enable / disable  verbose  CDR  debugging . < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > When  set  to  < literal > True < / literal > ,  verbose  updates 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													of  changes  in  CDR  information  will  be  logged .  Note  that  this  is  only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													of  use  when  debugging  CDR  behavior . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " enable " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< synopsis > Enable / disable  CDR  logging . < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > Define  whether  or  not  to  use  CDR  logging .  Setting  this  to  " no "  will  override 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													any  loading  of  backend  CDR  modules .   Default  is  " yes " . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " unanswered " > 
							 
						 
					
						
							
								
									
										
										
										
											2014-11-14 18:12:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													< synopsis > Log  calls  that  are  never  answered  and  don ' t  set  an  outgoing  party . < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													Define  whether  or  not  to  log  unanswered  calls  that  don ' t  involve  an  outgoing  party .  Setting 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													this  to  " yes "  will  make  calls  to  extensions  that  don ' t  answer  and  don ' t  set  a  side  B  channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													( such  as  by  using  the  Dial  application )  receive  CDR  log  entries .  If  this  option  is  set  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													" no " ,  then  those  log  entries  will  not  be  created .  Unanswered  calls  which  get  offered  to  an 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													outgoing  line  will  always  receive  log  entries  regardless  of  this  option ,  and  that  is  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													intended  behavior . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / para > 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " congestion " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< synopsis > Log  congested  calls . < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > Define  whether  or  not  to  log  congested  calls .  Setting  this  to  " yes "  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													report  each  call  that  fails  to  complete  due  to  congestion  conditions . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " endbeforehexten " > 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													< synopsis > Don ' t  produce  CDRs  while  executing  hangup  logic < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< para > As  each  CDR  for  a  channel  is  finished ,  its  end  time  is  updated 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														and  the  CDR  is  finalized .  When  a  channel  is  hung  up  and  hangup 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														logic  is  present  ( in  the  form  of  a  hangup  handler  or  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														< literal > h < / literal >  extension ) ,  a  new  CDR  is  generated  for  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														channel .  Any  statistics  are  gathered  from  this  new  CDR .  By  enabling 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														this  option ,  no  new  CDR  is  created  for  the  dialplan  logic  that  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														executed  in  < literal > h < / literal >  extensions  or  attached  hangup  handler 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														subroutines .  The  default  value  is  < literal > yes < / literal > ,  indicating 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
														that  a  CDR  will  be  generated  during  hangup  logic . < / para > 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " initiatedseconds " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< synopsis > Count  microseconds  for  billsec  purposes < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > Normally ,  the  < literal > billsec < / literal >  field  logged  to  the  CDR  backends 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													is  simply  the  end  time  ( hangup  time )  minus  the  answer  time  in  seconds .  Internally , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													asterisk  stores  the  time  in  terms  of  microseconds  and  seconds .  By  setting 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													initiatedseconds  to  < literal > yes < / literal > ,  you  can  force  asterisk  to  report  any  seconds 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													that  were  initiated  ( a  sort  of  round  up  method ) .  Technically ,  this  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													when  the  microsecond  part  of  the  end  time  is  greater  than  the  microsecond 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													part  of  the  answer  time ,  then  the  billsec  time  is  incremented  one  second . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " batch " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< synopsis > Submit  CDRs  to  the  backends  for  processing  in  batches < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > Define  the  CDR  batch  mode ,  where  instead  of  posting  the  CDR  at  the  end  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													every  call ,  the  data  will  be  stored  in  a  buffer  to  help  alleviate  load  on  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													asterisk  server . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< warning > < para > Use  of  batch  mode  may  result  in  data  loss  after  unsafe  asterisk  termination , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													i . e . ,  software  crash ,  power  failure ,  kill  - 9 ,  etc . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / warning > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " size " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< synopsis > The  maximum  number  of  CDRs  to  accumulate  before  triggering  a  batch < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > Define  the  maximum  number  of  CDRs  to  accumulate  in  the  buffer  before  posting 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													them  to  the  backend  engines .  batch  must  be  set  to  < literal > yes < / literal > . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " time " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< synopsis > The  maximum  time  to  accumulate  CDRs  before  triggering  a  batch < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > Define  the  maximum  time  to  accumulate  CDRs  before  posting  them  in  a  batch  to  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													backend  engines .  If  this  time  limit  is  reached ,  then  it  will  post  the  records ,  regardless  of  the  value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													defined  for  size .  batch  must  be  set  to  < literal > yes < / literal > . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< note > < para > Time  is  expressed  in  seconds . < / para > < / note > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " scheduleronly " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< synopsis > Post  batched  CDRs  on  their  own  thread  instead  of  the  scheduler < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > The  CDR  engine  uses  the  internal  asterisk  scheduler  to  determine  when  to  post 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													records .   Posting  can  either  occur  inside  the  scheduler  thread ,  or  a  new 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													thread  can  be  spawned  for  the  submission  of  every  batch .   For  small  batches , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													it  might  be  acceptable  to  just  use  the  scheduler  thread ,  so  set  this  to  < literal > yes < / literal > . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													For  large  batches ,  say  anything  over  size = 10 ,  a  new  thread  is  recommended ,  so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													set  this  to  < literal > no < / literal > . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< configOption  name = " safeshutdown " > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< synopsis > Block  shutdown  of  Asterisk  until  CDRs  are  submitted < / synopsis > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< description > < para > When  shutting  down  asterisk ,  you  can  block  until  the  CDRs  are  submitted .   If 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													you  don ' t ,  then  data  will  likely  be  lost .   You  can  always  check  the  size  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													the  CDR  batch  buffer  with  the  CLI  < astcli > cdr  status < / astcli >  command .   To  enable  blocking  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													submission  of  CDR  data  during  asterisk  shutdown ,  set  this  to  < literal > yes < / literal > . < / para > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													< / description > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												< / configOption > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											< / configObject > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										< / configFile > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									< / configInfo > 
							 
						 
					
						
							
								
									
										
										
										
											2012-07-11 02:06:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-06 21:17:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* The prime here should be similar in size to the channel container. */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef LOW_MEMORY 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define NUM_CDR_BUCKETS 61 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define NUM_CDR_BUCKETS 769 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define DEFAULT_ENABLED "1" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define DEFAULT_BATCHMODE "0" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define DEFAULT_UNANSWERED "0" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define DEFAULT_CONGESTION "0" 
  
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define DEFAULT_END_BEFORE_H_EXTEN "1" 
  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define DEFAULT_INITIATED_SECONDS "0" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define DEFAULT_BATCH_SIZE "100" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define MAX_BATCH_SIZE 1000 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define DEFAULT_BATCH_TIME "300" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define MAX_BATCH_TIME 86400 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define DEFAULT_BATCH_SCHEDULER_ONLY "0" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define DEFAULT_BATCH_SAFE_SHUTDOWN "1" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define CDR_DEBUG(mod_cfg, fmt, ...) \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									do  {  \
							 
						 
					
						
							
								
									
										
										
										
											2014-10-09 16:38:40 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ast_test_flag ( & ( mod_cfg ) - > general - > settings ,  CDR_DEBUG ) )  {  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_verbose ( ( fmt ) ,  # # __VA_ARGS__ ) ;  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  while  ( 0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_detach ( struct  ast_cdr  * cdr ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_submit_batch ( int  shutdown ) ;  
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  cdr_toggle_runtime_options ( void ) ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief The configuration settings for this module */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  module_config  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_cdr_config  * general ; 		/*< CDR global settings */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief The container for the module configuration */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  AO2_GLOBAL_OBJ_STATIC ( module_configs ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief The type definition for general options */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  aco_type  general_option  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. type  =  ACO_GLOBAL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " general " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. item_offset  =  offsetof ( struct  module_config ,  general ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. category  =  " ^general$ " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. category_match  =  ACO_WHITELIST , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * module_config_alloc ( void ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  module_config_destructor ( void  * obj ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief The file definition */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  aco_file  module_file_conf  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. filename  =  " cdr.conf " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. skip_category  =  " (^csv$|^custom$|^manager$|^odbc$|^pgsql$|^radius$|^sqlite$|^tds$|^mysql$) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. types  =  ACO_TYPES ( & general_option ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								CONFIG_INFO_CORE ( " cdr " ,  cfg_info ,  module_configs ,  module_config_alloc ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. files  =  ACO_FILES ( & module_file_conf ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  aco_type  * general_options [ ]  =  ACO_TYPES ( & general_option ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Dispose of a module config object */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  module_config_destructor ( void  * obj )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  module_config  * cfg  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cfg )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( cfg - > general ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Create a new module config object */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * module_config_alloc ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  module_config  * mod_cfg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_cdr_config  * cdr_config ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod_cfg  =  ao2_alloc ( sizeof ( * mod_cfg ) ,  module_config_destructor ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! mod_cfg )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_config  =  ao2_alloc ( sizeof ( * cdr_config ) ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr_config )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cdr_config ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod_cfg - > general  =  cdr_config ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  mod_cfg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Registration object for CDR backends */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_beitem  {  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									char  name [ 20 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  desc [ 80 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cdrbe  be ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_RWLIST_ENTRY ( cdr_beitem )  list ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  suspended : 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief List of registered backends */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  AST_RWLIST_HEAD_STATIC ( be_list ,  cdr_beitem ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief List of registered modifiers */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  AST_RWLIST_HEAD_STATIC ( mo_list ,  cdr_beitem ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Queued CDR waiting to be batched */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_batch_item  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_cdr  * cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_batch_item  * next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief The actual batch queue */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  cdr_batch  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_batch_item  * head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_batch_item  * tail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  * batch  =  NULL ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief The global sequence counter used for CDRs */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  global_cdr_sequence  =   0 ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Scheduler items */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_sched_context  * sched ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  cdr_sched  =  - 1 ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_MUTEX_DEFINE_STATIC ( cdr_sched_lock ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  pthread_t  cdr_thread  =  AST_PTHREADT_NULL ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Lock protecting modifications to the batch queue */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_MUTEX_DEFINE_STATIC ( cdr_batch_lock ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief These are used to wake up the CDR thread when there's work to do */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AST_MUTEX_DEFINE_STATIC ( cdr_pending_lock ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  ast_cond_t  cdr_pending_cond ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief A container of the active CDRs indexed by Party A channel id */  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  ao2_container  * active_cdrs_by_channel ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Message router for stasis messages regarding channel state */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  stasis_message_router  * stasis_router ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Our subscription for bridges */  
						 
					
						
							
								
									
										
											 
										
											
												Multiple revisions 399887,400138,400178,400180-400181
........
  r399887 | dlee | 2013-09-26 10:41:47 -0500 (Thu, 26 Sep 2013) | 1 line
  
  Minor performance bump by not allocate manager variable struct if we don't need it
........
  r400138 | dlee | 2013-09-30 10:24:00 -0500 (Mon, 30 Sep 2013) | 23 lines
  
  Stasis performance improvements
  
  This patch addresses several performance problems that were found in
  the initial performance testing of Asterisk 12.
  
  The Stasis dispatch object was allocated as an AO2 object, even though
  it has a very confined lifecycle. This was replaced with a straight
  ast_malloc().
  
  The Stasis message router was spending an inordinate amount of time
  searching hash tables. In this case, most of our routers had 6 or
  fewer routes in them to begin with. This was replaced with an array
  that's searched linearly for the route.
  
  We more heavily rely on AO2 objects in Asterisk 12, and the memset()
  in ao2_ref() actually became noticeable on the profile. This was
  #ifdef'ed to only run when AO2_DEBUG was enabled.
  
  After being misled by an erroneous comment in taskprocessor.c during
  profiling, the wrong comment was removed.
  
  Review: https://reviewboard.asterisk.org/r/2873/
........
  r400178 | dlee | 2013-09-30 13:26:27 -0500 (Mon, 30 Sep 2013) | 24 lines
  
  Taskprocessor optimization; switch Stasis to use taskprocessors
  
  This patch optimizes taskprocessor to use a semaphore for signaling,
  which the OS can do a better job at managing contention and waiting
  that we can with a mutex and condition.
  
  The taskprocessor execution was also slightly optimized to reduce the
  number of locks taken.
  
  The only observable difference in the taskprocessor implementation is
  that when the final reference to the taskprocessor goes away, it will
  execute all tasks to completion instead of discarding the unexecuted
  tasks.
  
  For systems where unnamed semaphores are not supported, a really
  simple semaphore implementation is provided. (Which gives identical
  performance as the original taskprocessor implementation).
  
  The way we ended up implementing Stasis caused the threadpool to be a
  burden instead of a boost to performance. This was switched to just
  use taskprocessors directly for subscriptions.
  
  Review: https://reviewboard.asterisk.org/r/2881/
........
  r400180 | dlee | 2013-09-30 13:39:34 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Optimize how Stasis forwards are dispatched
  
  This patch optimizes how forwards are dispatched in Stasis.
  
  Originally, forwards were dispatched as subscriptions that are invoked
  on the publishing thread. This did not account for the vast number of
  forwards we would end up having in the system, and the amount of work it
  would take to walk though the forward subscriptions.
  
  This patch modifies Stasis so that rather than walking the tree of
  forwards on every dispatch, when forwards and subscriptions are changed,
  the subscriber list for every topic in the tree is changed.
  
  This has a couple of benefits. First, this reduces the workload of
  dispatching messages. It also reduces contention when dispatching to
  different topics that happen to forward to the same aggregation topic
  (as happens with all of the channel, bridge and endpoint topics).
  
  Since forwards are no longer subscriptions, the bulk of this patch is
  simply changing stasis_subscription objects to stasis_forward objects
  (which, admittedly, I should have done in the first place.)
  
  Since this required me to yet again put in a growing array, I finally
  abstracted that out into a set of ast_vector macros in
  asterisk/vector.h.
  
  Review: https://reviewboard.asterisk.org/r/2883/
........
  r400181 | dlee | 2013-09-30 13:48:57 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Remove dispatch object allocation from Stasis publishing
  
  While looking for areas for performance improvement, I realized that an
  unused feature in Stasis was negatively impacting performance.
  
  When a message is sent to a subscriber, a dispatch object is allocated
  for the dispatch, containing the topic the message was published to, the
  subscriber the message is being sent to, and the message itself.
  
  The topic is actually unused by any subscriber in Asterisk today. And
  the subscriber is associated with the taskprocessor the message is being
  dispatched to.
  
  First, this patch removes the unused topic parameter from Stasis
  subscription callbacks.
  
  Second, this patch introduces the concept of taskprocessor local data,
  data that may be set on a taskprocessor and provided along with the data
  pointer when a task is pushed using the ast_taskprocessor_push_local()
  call. This allows the task to have both data specific to that
  taskprocessor, in addition to data specific to that invocation.
  
  With those two changes, the dispatch object can be removed completely,
  and the message is simply refcounted and sent directly to the
  taskprocessor.
  
  Review: https://reviewboard.asterisk.org/r/2884/
........
Merged revisions 399887,400138,400178,400180-400181 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-30 18:55:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  stasis_forward  * bridge_subscription ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Our subscription for channels */  
						 
					
						
							
								
									
										
											 
										
											
												Multiple revisions 399887,400138,400178,400180-400181
........
  r399887 | dlee | 2013-09-26 10:41:47 -0500 (Thu, 26 Sep 2013) | 1 line
  
  Minor performance bump by not allocate manager variable struct if we don't need it
........
  r400138 | dlee | 2013-09-30 10:24:00 -0500 (Mon, 30 Sep 2013) | 23 lines
  
  Stasis performance improvements
  
  This patch addresses several performance problems that were found in
  the initial performance testing of Asterisk 12.
  
  The Stasis dispatch object was allocated as an AO2 object, even though
  it has a very confined lifecycle. This was replaced with a straight
  ast_malloc().
  
  The Stasis message router was spending an inordinate amount of time
  searching hash tables. In this case, most of our routers had 6 or
  fewer routes in them to begin with. This was replaced with an array
  that's searched linearly for the route.
  
  We more heavily rely on AO2 objects in Asterisk 12, and the memset()
  in ao2_ref() actually became noticeable on the profile. This was
  #ifdef'ed to only run when AO2_DEBUG was enabled.
  
  After being misled by an erroneous comment in taskprocessor.c during
  profiling, the wrong comment was removed.
  
  Review: https://reviewboard.asterisk.org/r/2873/
........
  r400178 | dlee | 2013-09-30 13:26:27 -0500 (Mon, 30 Sep 2013) | 24 lines
  
  Taskprocessor optimization; switch Stasis to use taskprocessors
  
  This patch optimizes taskprocessor to use a semaphore for signaling,
  which the OS can do a better job at managing contention and waiting
  that we can with a mutex and condition.
  
  The taskprocessor execution was also slightly optimized to reduce the
  number of locks taken.
  
  The only observable difference in the taskprocessor implementation is
  that when the final reference to the taskprocessor goes away, it will
  execute all tasks to completion instead of discarding the unexecuted
  tasks.
  
  For systems where unnamed semaphores are not supported, a really
  simple semaphore implementation is provided. (Which gives identical
  performance as the original taskprocessor implementation).
  
  The way we ended up implementing Stasis caused the threadpool to be a
  burden instead of a boost to performance. This was switched to just
  use taskprocessors directly for subscriptions.
  
  Review: https://reviewboard.asterisk.org/r/2881/
........
  r400180 | dlee | 2013-09-30 13:39:34 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Optimize how Stasis forwards are dispatched
  
  This patch optimizes how forwards are dispatched in Stasis.
  
  Originally, forwards were dispatched as subscriptions that are invoked
  on the publishing thread. This did not account for the vast number of
  forwards we would end up having in the system, and the amount of work it
  would take to walk though the forward subscriptions.
  
  This patch modifies Stasis so that rather than walking the tree of
  forwards on every dispatch, when forwards and subscriptions are changed,
  the subscriber list for every topic in the tree is changed.
  
  This has a couple of benefits. First, this reduces the workload of
  dispatching messages. It also reduces contention when dispatching to
  different topics that happen to forward to the same aggregation topic
  (as happens with all of the channel, bridge and endpoint topics).
  
  Since forwards are no longer subscriptions, the bulk of this patch is
  simply changing stasis_subscription objects to stasis_forward objects
  (which, admittedly, I should have done in the first place.)
  
  Since this required me to yet again put in a growing array, I finally
  abstracted that out into a set of ast_vector macros in
  asterisk/vector.h.
  
  Review: https://reviewboard.asterisk.org/r/2883/
........
  r400181 | dlee | 2013-09-30 13:48:57 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Remove dispatch object allocation from Stasis publishing
  
  While looking for areas for performance improvement, I realized that an
  unused feature in Stasis was negatively impacting performance.
  
  When a message is sent to a subscriber, a dispatch object is allocated
  for the dispatch, containing the topic the message was published to, the
  subscriber the message is being sent to, and the message itself.
  
  The topic is actually unused by any subscriber in Asterisk today. And
  the subscriber is associated with the taskprocessor the message is being
  dispatched to.
  
  First, this patch removes the unused topic parameter from Stasis
  subscription callbacks.
  
  Second, this patch introduces the concept of taskprocessor local data,
  data that may be set on a taskprocessor and provided along with the data
  pointer when a task is pushed using the ast_taskprocessor_push_local()
  call. This allows the task to have both data specific to that
  taskprocessor, in addition to data specific to that invocation.
  
  With those two changes, the dispatch object can be removed completely,
  and the message is simply refcounted and sent directly to the
  taskprocessor.
  
  Review: https://reviewboard.asterisk.org/r/2884/
........
Merged revisions 399887,400138,400178,400180-400181 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-30 18:55:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  stasis_forward  * channel_subscription ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Our subscription for parking */  
						 
					
						
							
								
									
										
											 
										
											
												Multiple revisions 399887,400138,400178,400180-400181
........
  r399887 | dlee | 2013-09-26 10:41:47 -0500 (Thu, 26 Sep 2013) | 1 line
  
  Minor performance bump by not allocate manager variable struct if we don't need it
........
  r400138 | dlee | 2013-09-30 10:24:00 -0500 (Mon, 30 Sep 2013) | 23 lines
  
  Stasis performance improvements
  
  This patch addresses several performance problems that were found in
  the initial performance testing of Asterisk 12.
  
  The Stasis dispatch object was allocated as an AO2 object, even though
  it has a very confined lifecycle. This was replaced with a straight
  ast_malloc().
  
  The Stasis message router was spending an inordinate amount of time
  searching hash tables. In this case, most of our routers had 6 or
  fewer routes in them to begin with. This was replaced with an array
  that's searched linearly for the route.
  
  We more heavily rely on AO2 objects in Asterisk 12, and the memset()
  in ao2_ref() actually became noticeable on the profile. This was
  #ifdef'ed to only run when AO2_DEBUG was enabled.
  
  After being misled by an erroneous comment in taskprocessor.c during
  profiling, the wrong comment was removed.
  
  Review: https://reviewboard.asterisk.org/r/2873/
........
  r400178 | dlee | 2013-09-30 13:26:27 -0500 (Mon, 30 Sep 2013) | 24 lines
  
  Taskprocessor optimization; switch Stasis to use taskprocessors
  
  This patch optimizes taskprocessor to use a semaphore for signaling,
  which the OS can do a better job at managing contention and waiting
  that we can with a mutex and condition.
  
  The taskprocessor execution was also slightly optimized to reduce the
  number of locks taken.
  
  The only observable difference in the taskprocessor implementation is
  that when the final reference to the taskprocessor goes away, it will
  execute all tasks to completion instead of discarding the unexecuted
  tasks.
  
  For systems where unnamed semaphores are not supported, a really
  simple semaphore implementation is provided. (Which gives identical
  performance as the original taskprocessor implementation).
  
  The way we ended up implementing Stasis caused the threadpool to be a
  burden instead of a boost to performance. This was switched to just
  use taskprocessors directly for subscriptions.
  
  Review: https://reviewboard.asterisk.org/r/2881/
........
  r400180 | dlee | 2013-09-30 13:39:34 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Optimize how Stasis forwards are dispatched
  
  This patch optimizes how forwards are dispatched in Stasis.
  
  Originally, forwards were dispatched as subscriptions that are invoked
  on the publishing thread. This did not account for the vast number of
  forwards we would end up having in the system, and the amount of work it
  would take to walk though the forward subscriptions.
  
  This patch modifies Stasis so that rather than walking the tree of
  forwards on every dispatch, when forwards and subscriptions are changed,
  the subscriber list for every topic in the tree is changed.
  
  This has a couple of benefits. First, this reduces the workload of
  dispatching messages. It also reduces contention when dispatching to
  different topics that happen to forward to the same aggregation topic
  (as happens with all of the channel, bridge and endpoint topics).
  
  Since forwards are no longer subscriptions, the bulk of this patch is
  simply changing stasis_subscription objects to stasis_forward objects
  (which, admittedly, I should have done in the first place.)
  
  Since this required me to yet again put in a growing array, I finally
  abstracted that out into a set of ast_vector macros in
  asterisk/vector.h.
  
  Review: https://reviewboard.asterisk.org/r/2883/
........
  r400181 | dlee | 2013-09-30 13:48:57 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Remove dispatch object allocation from Stasis publishing
  
  While looking for areas for performance improvement, I realized that an
  unused feature in Stasis was negatively impacting performance.
  
  When a message is sent to a subscriber, a dispatch object is allocated
  for the dispatch, containing the topic the message was published to, the
  subscriber the message is being sent to, and the message itself.
  
  The topic is actually unused by any subscriber in Asterisk today. And
  the subscriber is associated with the taskprocessor the message is being
  dispatched to.
  
  First, this patch removes the unused topic parameter from Stasis
  subscription callbacks.
  
  Second, this patch introduces the concept of taskprocessor local data,
  data that may be set on a taskprocessor and provided along with the data
  pointer when a task is pushed using the ast_taskprocessor_push_local()
  call. This allows the task to have both data specific to that
  taskprocessor, in addition to data specific to that invocation.
  
  With those two changes, the dispatch object can be removed completely,
  and the message is simply refcounted and sent directly to the
  taskprocessor.
  
  Review: https://reviewboard.asterisk.org/r/2884/
........
Merged revisions 399887,400138,400178,400180-400181 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-30 18:55:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  stasis_forward  * parking_subscription ;  
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief The parent topic for all topics we want to aggregate for CDRs */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  stasis_topic  * cdr_topic ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief A message type used to synchronize with the CDR topic */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								STASIS_MESSAGE_TYPE_DEFN_LOCAL ( cdr_sync_message_type ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  cdr_object ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Return types for \ref process_bridge_enter functions */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								enum  process_bridge_enter_results  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  The  CDR  was  the  only  party  in  the  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BRIDGE_ENTER_ONLY_PARTY , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  The  CDR  was  able  to  obtain  a  Party  B  from  some  other  party  already  in  the  bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BRIDGE_ENTER_OBTAINED_PARTY_B , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  The  CDR  was  not  able  to  obtain  a  Party  B 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BRIDGE_ENTER_NO_PARTY_B , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  This  CDR  can ' t  handle  a  bridge  enter  message  and  a  new  CDR  needs  to  be  created 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BRIDGE_ENTER_NEED_CDR , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  A  virtual  table  used  for  \ ref  cdr_object . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Note  that  all  functions  are  optional  -  if  a  subclass  does  not  need  an 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  implementation ,  it  is  safe  to  leave  it  NULL . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_object_fn_table  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*! \brief Name of the subclass */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  An  initialization  function .  This  will  be  called  automatically 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  when  a  \ ref  cdr_object  is  switched  to  this  type  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ ref  cdr_object_transition_state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  cdr  The  \ ref  cdr_object  that  was  just  transitioned 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  ( *  const  init_function ) ( struct  cdr_object  * cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  Process  a  Party  A  update  for  the  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  cdr  The  \ ref  cdr_object  to  process  the  update 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  snapshot  The  snapshot  for  the  CDR ' s  Party  A 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  0  the  CDR  handled  the  update  or  ignored  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  1  the  CDR  is  finalized  and  a  new  one  should  be  made  to  handle  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ( *  const  process_party_a ) ( struct  cdr_object  * cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_channel_snapshot  * snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  Process  a  Party  B  update  for  the  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  cdr  The  \ ref  cdr_object  to  process  the  update 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  snapshot  The  snapshot  for  the  CDR ' s  Party  B 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									void  ( *  const  process_party_b ) ( struct  cdr_object  * cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_channel_snapshot  * snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  Process  the  beginning  of  a  dial .  A  dial  message  implies  one  of  two 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  things : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  The  \ ref  cdr_object ' s  Party  A  has  been  originated 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  The  \ ref  cdr_object ' s  Party  A  is  dialing  its  Party  B 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  cdr  The  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  caller  The  originator  of  the  dial  attempt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  peer  The  destination  of  the  dial  attempt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  0  if  the  parties  in  the  dial  were  handled  by  this  CDR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  1  if  the  parties  could  not  be  handled  by  this  CDR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ( *  const  process_dial_begin ) ( struct  cdr_object  * cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_channel_snapshot  * caller , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_channel_snapshot  * peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  Process  the  end  of  a  dial .  At  the  end  of  a  dial ,  a  CDR  can  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  transitioned  into  one  of  two  states  -  DialedPending 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  ( \ ref  dialed_pending_state_fn_table )  or  Finalized 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  ( \ ref  finalized_state_fn_table ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  cdr  The  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  caller  The  originator  of  the  dial  attempt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  peer  the  Destination  of  the  dial  attempt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  dial_status  What  happened 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  0  if  the  parties  in  the  dial  were  handled  by  this  CDR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  1  if  the  parties  could  not  be  handled  by  this  CDR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ( *  const  process_dial_end ) ( struct  cdr_object  * cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_channel_snapshot  * caller , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_channel_snapshot  * peer , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											const  char  * dial_status ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  Process  the  entering  of  a  bridge  by  this  CDR .  The  purpose  of  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  callback  is  to  have  the  CDR  prepare  itself  for  the  bridge  and  attempt  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  find  a  valid  Party  B .  The  act  of  creating  new  CDRs  based  on  the  entering 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  of  this  channel  into  the  bridge  is  handled  by  the  higher  level  message 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  handler . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  Note  that  this  handler  is  for  when  a  channel  enters  into  a  " normal " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  bridge ,  where  people  actually  talk  to  each  other .  Parking  is  its  own 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  thing . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  \ param  cdr  The  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  bridge  The  bridge  that  the  Party  A  just  entered  into 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  channel  The  \ ref  ast_channel_snapshot  for  this  CDR ' s  Party  A 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  \ retval  process_bridge_enter_results  Defines  whether  or  not  this  CDR  was  able 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  to  fully  handle  the  bridge  enter  message . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  process_bridge_enter_results  ( *  const  process_bridge_enter ) ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  cdr_object  * cdr , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											struct  ast_bridge_snapshot  * bridge , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_channel_snapshot  * channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  Process  entering  into  a  parking  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  cdr  The  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  bridge  The  parking  bridge  that  Party  A  just  entered  into 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  channel  The  \ ref  ast_channel_snapshot  for  this  CDR ' s  Party  A 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  0  This  CDR  successfully  transitioned  itself  into  the  parked  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  1  This  CDR  couldn ' t  handle  the  parking  transition  and  we  need  a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *   new  CDR . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ( *  const  process_parking_bridge_enter ) ( struct  cdr_object  * cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_bridge_snapshot  * bridge , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_channel_snapshot  * channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  Process  the  leaving  of  a  bridge  by  this  CDR . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  cdr  The  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  bridge  The  bridge  that  the  Party  A  just  left 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  channel  The  \ ref  ast_channel_snapshot  for  this  CDR ' s  Party  A 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  0  This  CDR  left  successfully 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  1  Error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ( *  const  process_bridge_leave ) ( struct  cdr_object  * cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_bridge_snapshot  * bridge , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_channel_snapshot  * channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ brief  Process  an  update  informing  us  that  the  channel  got  itself  parked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  cdr  The  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ param  channel  The  parking  information  for  this  CDR ' s  party  A 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  0  This  CDR  successfully  parked  itself 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  \ retval  1  This  CDR  couldn ' t  handle  the  park 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ( *  const  process_parked_channel ) ( struct  cdr_object  * cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  ast_parked_call_payload  * parking_info ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  base_process_party_a ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot ) ;  
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  process_bridge_enter_results  base_process_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel ) ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  base_process_bridge_leave ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  base_process_dial_end ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer ,  const  char  * dial_status ) ;  
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  base_process_parked_channel ( struct  cdr_object  * cdr ,  struct  ast_parked_call_payload  * parking_info ) ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  single_state_init_function ( struct  cdr_object  * cdr ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  single_state_process_party_b ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  single_state_process_dial_begin ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer ) ;  
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  process_bridge_enter_results  single_state_process_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel ) ;  
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  single_state_process_parking_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel ) ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  The  virtual  table  for  the  Single  state . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  A  \ ref  cdr_object  starts  off  in  this  state .  This  represents  a  channel  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  has  no  Party  B  information  itself . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  A  \ ref  cdr_object  from  this  state  can  go  into  any  of  the  following  states : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  dial_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  bridge_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  finalized_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_object_fn_table  single_state_fn_table  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " Single " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. init_function  =  single_state_init_function , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_party_a  =  base_process_party_a , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_party_b  =  single_state_process_party_b , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_dial_begin  =  single_state_process_dial_begin , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_dial_end  =  base_process_dial_end , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_bridge_enter  =  single_state_process_bridge_enter , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. process_parking_bridge_enter  =  single_state_process_parking_bridge_enter , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. process_bridge_leave  =  base_process_bridge_leave , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. process_parked_channel  =  base_process_parked_channel , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  dial_state_process_party_b ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  dial_state_process_dial_begin ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  dial_state_process_dial_end ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer ,  const  char  * dial_status ) ;  
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  process_bridge_enter_results  dial_state_process_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel ) ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  The  virtual  table  for  the  Dial  state . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  A  \ ref  cdr_object  that  has  begun  a  dial  operation .  This  state  is  entered  when 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  Party  A  for  a  CDR  is  determined  to  be  dialing  out  to  a  Party  B  or  when 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  a  CDR  is  for  an  originated  channel  ( in  which  case  the  Party  A  information  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  originated  channel ,  and  there  is  no  Party  B ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  A  \ ref  cdr_object  from  this  state  can  go  in  any  of  the  following  states : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  dialed_pending_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  bridge_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  finalized_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_object_fn_table  dial_state_fn_table  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " Dial " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_party_a  =  base_process_party_a , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_party_b  =  dial_state_process_party_b , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_dial_begin  =  dial_state_process_dial_begin , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_dial_end  =  dial_state_process_dial_end , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_bridge_enter  =  dial_state_process_bridge_enter , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_bridge_leave  =  base_process_bridge_leave , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  dialed_pending_state_process_party_a ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  dialed_pending_state_process_dial_begin ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer ) ;  
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  process_bridge_enter_results  dialed_pending_state_process_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel ) ;  
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  dialed_pending_state_process_parking_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel ) ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  The  virtual  table  for  the  Dialed  Pending  state . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  A  \ ref  cdr_object  that  has  successfully  finished  a  dial  operation ,  but  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  don ' t  know  what  they ' re  going  to  do  yet .  It ' s  theoretically  possible  to  dial 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  a  party  and  then  have  that  party  not  be  bridged  with  the  caller ;  likewise , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  an  origination  can  complete  and  the  channel  go  off  and  execute  dialplan .  The 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  pending  state  acts  as  a  bridge  between  either : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  Entering  a  bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  Getting  a  new  CDR  for  new  dialplan  execution 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  Switching  from  being  originated  to  executing  dialplan 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  A  \ ref  cdr_object  from  this  state  can  go  in  any  of  the  following  states : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  single_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  dialed_pending_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  bridge_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  finalized_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_object_fn_table  dialed_pending_state_fn_table  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " DialedPending " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_party_a  =  dialed_pending_state_process_party_a , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_dial_begin  =  dialed_pending_state_process_dial_begin , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_bridge_enter  =  dialed_pending_state_process_bridge_enter , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. process_parking_bridge_enter  =  dialed_pending_state_process_parking_bridge_enter , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. process_bridge_leave  =  base_process_bridge_leave , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. process_parked_channel  =  base_process_parked_channel , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_state_process_party_b ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_state_process_bridge_leave ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  The  virtual  table  for  the  Bridged  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  A  \ ref  cdr_object  enters  this  state  when  it  receives  notification  that  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  channel  has  entered  a  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  A  \ ref  cdr_object  from  this  state  can  go  to : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  *  \ ref  finalized_state_fn_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_object_fn_table  bridge_state_fn_table  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " Bridged " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_party_a  =  base_process_party_a , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_party_b  =  bridge_state_process_party_b , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_bridge_leave  =  bridge_state_process_bridge_leave , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. process_parked_channel  =  base_process_parked_channel , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  parked_state_process_bridge_leave ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  The  virtual  table  for  the  Parked  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Parking  is  weird .  Unlike  typical  bridges ,  it  has  to  be  treated  somewhat 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  uniquely  -  a  channel  in  a  parking  bridge  ( which  is  a  subclass  of  a  holding 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  bridge )  has  to  be  handled  as  if  the  channel  went  into  an  application . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  However ,  when  the  channel  comes  out ,  we  need  a  new  CDR  -  unlike  the  Single 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  state . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_object_fn_table  parked_state_fn_table  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " Parked " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_party_a  =  base_process_party_a , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_bridge_leave  =  parked_state_process_bridge_leave , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_parked_channel  =  base_process_parked_channel , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  finalized_state_init_function ( struct  cdr_object  * cdr ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  finalized_state_process_party_a ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  The  virtual  table  for  the  finalized  state . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Once  in  the  finalized  state ,  the  CDR  is  done .  No  modifications  can  be  made 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  to  the  CDR . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_object_fn_table  finalized_state_fn_table  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name  =  " Finalized " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. init_function  =  finalized_state_init_function , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. process_party_a  =  finalized_state_process_party_a , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									. process_bridge_enter  =  base_process_bridge_enter , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief A wrapper object around a snapshot.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Fields  that  are  mutable  by  the  CDR  engine  are  replicated  here . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_object_snapshot  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * snapshot ;   /*!< The channel snapshot */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  userfield [ AST_MAX_USER_FIELD ] ;      /*!< Userfield for the channel */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  flags ;                      /*!< Specific flags for this party */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  varshead  variables ;               /*!< CDR variables for the channel */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief An in-memory representation of an active CDR */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  cdr_object  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object_snapshot  party_a ;      /*!< The Party A information */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object_snapshot  party_b ;      /*!< The Party B information */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object_fn_table  * fn_table ;    /*!< The current virtual table */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									enum  ast_cdr_disposition  disposition ;    /*!< The disposition of the CDR */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  start ;                    /*!< When this CDR was created */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  answer ;                   /*!< Either when the channel was answered, or when the path between channels was established */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timeval  end ;                      /*!< When this CDR was finalized */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  int  sequence ;                   /*!< A monotonically increasing number for each CDR */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_flags  flags ;                  /*!< Flags on the CDR */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_DECLARE_STRING_FIELDS ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_STRING_FIELD ( linkedid ) ;          /*!< Linked ID. Cached here as it may change out from party A, which must be immutable */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_STRING_FIELD ( uniqueid ) ; 			/*!< Unique id of party A. Cached here as it is the primary key of this CDR */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_STRING_FIELD ( name ) ;              /*!< Channel name of party A. Cached here as the party A address may change */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_STRING_FIELD ( bridge ) ;            /*!< The bridge the party A happens to be in. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_STRING_FIELD ( appl ) ;              /*!< The last accepted application party A was in */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_STRING_FIELD ( data ) ;              /*!< The data for the last accepted application party A was in */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												main/cdrs: Preserve context/extension when executing a Macro or GoSub
The context/extension in a CDR is generally considered the destination of a
call. When looking at a 2-party call CDR, users will typically be presented
with the following:
context    exten      channel     dest_channel app  data
default    1000       SIP/8675309 SIP/1000     Dial SIP/1000,,20
However, if the Dial actually takes place in a Macro, the current behaviour
in 12 will result in the following CDR:
context    exten      channel     dest_channel app  data
macro-dial s          SIP/8675309 SIP/1000     Dial SIP/1000,,20
The same is true of a GoSub:
context    exten      channel     dest_channel app  data
subs       dial_stuff SIP/8675309 SIP/1000     Dial SIP/1000,,20
This generally makes the context/exten fields less than useful.
It isn't hard to preserve these values in the CDR state machine; however, we
need to have something that informs us when a channel is executing a
subroutine. Prior to this patch, there isn't anything that does this.
This patch solves this problem by adding a new channel flag,
AST_FLAG_SUBROUTINE_EXEC. This flag is set on a channel when it executes a
Macro or a GoSub. The CDR engine looks for this value when updating a Party A
snapshot; if the flag is present, we don't override the context/exten on the
main CDR object. In a funny quirk, executing a hangup handler must *not* abide
by this logic, as the endbeforehexten logic assumes that the user wants to see
data that occurs in hangup logic, which includes those subroutines. Since
those execute outside of a typical Dial operation (and will typically have
their own dedicated CDR anyway), this is unlikely to cause any heartburn.
Review: https://reviewboard.asterisk.org/r/3962/
ASTERISK-24254 #close
Reported by: tm1000, Tony Lewis
Tested by: Tony Lewis
........
Merged revisions 422718 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 422719 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@422720 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-09-05 22:04:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_STRING_FIELD ( context ) ;           /*!< The accepted context for Party A */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_STRING_FIELD ( exten ) ;             /*!< The accepted extension for Party A */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * next ;                 /*!< The next CDR object in the chain */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * last ;                 /*!< The last CDR object in the chain */ 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-18 16:30:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  is_root ;                             /*!< True if this is the first CDR in the chain */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Copy  variables  from  one  list  to  another 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  to_list  destination 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  from_list  source 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  The  number  of  copied  variables 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  copy_variables ( struct  varshead  * to_list ,  struct  varshead  * from_list )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:24:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_var_t  * variables ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_var_t  * newvariable ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * var ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * val ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  x  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( from_list ,  variables ,  entries )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:24:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  =  ast_var_name ( variables ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_strlen_zero ( var ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										val  =  ast_var_value ( variables ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_strlen_zero ( val ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										newvariable  =  ast_var_assign ( var ,  val ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( newvariable )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_LIST_INSERT_HEAD ( to_list ,  newvariable ,  entries ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:24:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											+ + x ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  x ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Delete  all  variables  from  a  variable  list 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  headp  The  head  pointer  to  the  variable  list  to  delete 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  free_variables ( struct  varshead  * headp )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_var_t  * vardata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( vardata  =  AST_LIST_REMOVE_HEAD ( headp ,  entries ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_var_delete ( vardata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Copy  a  snapshot  and  its  details 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  dst  The  destination 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  src  The  source 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_snapshot_copy ( struct  cdr_object_snapshot  * dst ,  struct  cdr_object_snapshot  * src )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( dst - > snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_t_ref ( dst - > snapshot ,  - 1 ,  " release old snapshot during copy " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dst - > snapshot  =  src - > snapshot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_t_ref ( dst - > snapshot ,  + 1 ,  " bump new snapshot during copy " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									strcpy ( dst - > userfield ,  src - > userfield ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dst - > flags  =  src - > flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									copy_variables ( & dst - > variables ,  & src - > variables ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Transition  a  \ ref  cdr_object  to  a  new  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr  The  \ ref  cdr_object  to  transition 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  fn_table  The  \ ref  cdr_object_fn_table  state  to  go  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_transition_state ( struct  cdr_object  * cdr ,  struct  cdr_object_fn_table  * fn_table )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									CDR_DEBUG ( mod_cfg ,  " %p - Transitioning CDR for %s from state %s to %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr ,  cdr - > party_a . snapshot - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr - > fn_table  ?  cdr - > fn_table - > name  :  " NONE " ,  fn_table - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr - > fn_table  =  fn_table ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr - > fn_table - > init_function )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr - > fn_table - > init_function ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \internal
  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Hash  function  for  containers  of  CDRs  indexing  by  Party  A  uniqueid  */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  cdr_object_channel_hash_fn ( const  void  * obj ,  const  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  struct  cdr_object  * cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * key ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( flags  &  ( OBJ_POINTER  |  OBJ_KEY  |  OBJ_PARTIAL_KEY ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										key  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  OBJ_POINTER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										key  =  cdr - > uniqueid ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ast_str_case_hash ( key ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \internal
  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Comparison  function  for  containers  of  CDRs  indexing  by  Party  A  uniqueid 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  cdr_object_channel_cmp_fn ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    struct  cdr_object  * left  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    struct  cdr_object  * right  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const  char  * right_key  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  cmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    switch  ( flags  &  ( OBJ_POINTER  |  OBJ_KEY  |  OBJ_PARTIAL_KEY ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  OBJ_POINTER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        right_key  =  right - > uniqueid ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        /* Fall through */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  OBJ_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cmp  =  strcmp ( left - > uniqueid ,  right_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  OBJ_PARTIAL_KEY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  We  could  also  use  a  partial  key  struct  containing  a  length 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  so  strlen ( )  does  not  get  called  for  every  comparison  instead . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cmp  =  strncmp ( left - > uniqueid ,  right_key ,  strlen ( right_key ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        /* Sort can only work on something with a full or partial key. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cmp  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  cmp  ?  0  :  CMP_MATCH ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  \ ref  cdr_object  Destructor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_dtor ( void  * obj )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_var_t  * it_var ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( cdr - > party_a . snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( cdr - > party_b . snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( it_var  =  AST_LIST_REMOVE_HEAD ( & cdr - > party_a . variables ,  entries ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_var_delete ( it_var ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( it_var  =  AST_LIST_REMOVE_HEAD ( & cdr - > party_b . variables ,  entries ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_var_delete ( it_var ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_free_memory ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-18 16:30:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* CDR destruction used to work by calling ao2_cleanup(next) and
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  allowing  the  chain  to  destroy  itself  neatly .  Unfortunately ,  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  really  long  chains ,  this  can  result  in  a  stack  overflow .  So  now 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  when  the  root  CDR  is  destroyed ,  it  is  responsible  for  unreffing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  all  CDRs  in  the  chain 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr - > is_root )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  cdr_object  * curr  =  cdr - > next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  cdr_object  * next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( curr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											next  =  curr - > next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_cleanup ( curr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											curr  =  next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  \ ref  cdr_object  constructor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  chan  The  \ ref  ast_channel_snapshot  that  is  the  CDR ' s  Party  A 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  implicitly  sets  the  state  of  the  newly  created  CDR  to  the  Single  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  ( \ ref  single_state_fn_table ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  cdr_object  * cdr_object_alloc ( struct  ast_channel_snapshot  * chan )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( chan  ! =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr  =  ao2_alloc ( sizeof ( * cdr ) ,  cdr_object_dtor ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr - > last  =  cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_string_field_init ( cdr ,  64 ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-06 20:03:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_cleanup ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_string_field_set ( cdr ,  uniqueid ,  chan - > uniqueid ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_string_field_set ( cdr ,  name ,  chan - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( cdr ,  linkedid ,  chan - > linkedid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr - > disposition  =  AST_CDR_NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr - > sequence  =  ast_atomic_fetchadd_int ( & global_cdr_sequence ,  + 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr - > party_a . snapshot  =  chan ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_t_ref ( cdr - > party_a . snapshot ,  + 1 ,  " bump snapshot during CDR creation " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									CDR_DEBUG ( mod_cfg ,  " %p - Created CDR for channel %s \n " ,  cdr ,  chan - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & single_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Create  a  new  \ ref  cdr_object  and  append  it  to  an  existing  chain 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr  The  \ ref  cdr_object  to  append  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  cdr_object  * cdr_object_create_and_append ( struct  cdr_object  * cdr )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * new_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr_last ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_last  =  cdr - > last ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									new_cdr  =  cdr_object_alloc ( cdr_last - > party_a . snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! new_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									new_cdr - > disposition  =  AST_CDR_NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Copy over the linkedid, as it may have changed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( new_cdr ,  linkedid ,  cdr_last - > linkedid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( new_cdr ,  appl ,  cdr_last - > appl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( new_cdr ,  data ,  cdr_last - > data ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												main/cdr: Copy context/exten on chained CDRs for parallel dials in subroutines
When a parallel dial occurs, a new CDR will be created for each dial
attempt that is made. In most circumstances, the act of creating each
CDR in the chain will include a step that updates the Party A snapshot,
which causes the context/extension of the Party A to be copied onto the
CDR object.
However, when the Party A is in a subroutine, we explicitly do *not*
copy the context/extension onto the CDR. This prevents the Macro or
GoSub routine name from blowing away the context/extension that the
channel was originally executing in. For the original CDR, this is not a
problem: the original CDR already recorded the last known 'good' state
of the channel just prior to it going into the subroutine. However, for
newly generated CDRs in a chain, there is no context/extension set on
them. Since we are in a subroutine, we will never set the Party A's
context/extension on the CDR, and we end up with a CDR with no
destination recorded on it.
This patch updates the creation of a chained CDR such that it copies
over the original CDR's context/extension. This is the last known "good"
state of the CDR, and is a reasonable starting point for the newly
generated CDR. In the case where we are not in a subroutine, subsequent
code will update the location of the CDR from the Party A information;
in the case where we are in a subroutine, the context/extension on the
original CDR is the correct information.
ASTERISK-24443 #close
Change-Id: I6a3ef0d6e458d3b9b30572feaec70f2964f3bc2a
											 
										 
										
											2015-06-12 14:28:47 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_string_field_set ( new_cdr ,  context ,  cdr_last - > context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( new_cdr ,  exten ,  cdr_last - > exten ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-06-14 19:48:26 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  If  the  current  CDR  says  to  disable  all  future  ones , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  keep  the  disable  chain  going 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & cdr_last - > flags ,  AST_CDR_FLAG_DISABLE_ALL ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_set_flag ( & new_cdr - > flags ,  AST_CDR_FLAG_DISABLE_ALL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Copy over other Party A information */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_snapshot_copy ( & new_cdr - > party_a ,  & cdr_last - > party_a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Append the CDR to the end of the list */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr - > next ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										it_cdr - > last  =  new_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									it_cdr - > last  =  new_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									it_cdr - > next  =  new_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  new_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Return  whether  or  not  a  channel  has  changed  its  state  in  the  dialplan ,  subject 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  to  endbeforehexten  logic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  old_snapshot  The  previous  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  new_snapshot  The  new  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  if  the  state  has  not  changed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  1  if  the  state  changed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  snapshot_cep_changed ( struct  ast_channel_snapshot  * old_snapshot ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * new_snapshot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If we ignore hangup logic, don't indicate that we're executing anything new */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_END_BEFORE_H_EXTEN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ast_test_flag ( & new_snapshot - > softhangup_flags ,  AST_SOFTHANGUP_HANGUP_EXEC ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix FRACK message from external redirects; handle outbound channels better
This patch does the following:
 * It simplifies the Dial handling in CDRs. As a rule, the caller in a dial
   relationship is always the Party A. There was some logic present in the
   handling of the dial message that could, conceivably, pick the caller
   as Party A for the beginning of the dial and the peer as Party A for the
   end of the dial. This shouldn't have happened if the code in the bridging
   framework was doing its job; however, that was broken and it led to the
   FRACK. As it is, this code was overly ocmplex and not needed: the caller,
   if present, should always be Party A. Period.
 * It properly checks to see if a channel will continue on in the dialplan.
   ast_check_hangup - much like cake at the end - is a lie. It will tell
   you that you are hungup when you are not. Do not believe it.
   I would make this function tell the truth, but I'm nervous that we've been
   depending on it sitting on its throne of lies for far too long, and it would
   probably break lots of things. So I'm just checking the "internal" soft
   hangup flags, like everyone else.
(closes issue ASTERISK-22060)
Reported by: Mark Michelson
(issue ASTERISK-21831)
Reported by: Matt Jordan
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394290 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-13 23:28:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* When Party A is originated to an application and the application exits, the stack
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  will  attempt  to  clear  the  application  and  restore  the  dummy  originate  application 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  of  " AppDialX " .  Ignore  application  changes  to  AppDialX  as  a  result . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-02 02:32:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( strcmp ( new_snapshot - > appl ,  old_snapshot - > appl )  & &  strncasecmp ( new_snapshot - > appl ,  " appdial " ,  7 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ( strcmp ( new_snapshot - > context ,  old_snapshot - > context ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  strcmp ( new_snapshot - > exten ,  old_snapshot - > exten ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  new_snapshot - > priority  ! =  old_snapshot - > priority ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Return  whether  or  not  a  \ ref  ast_channel_snapshot  is  for  a  channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  that  was  created  as  the  result  of  a  dial  operation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  the  channel  was  not  created  as  the  result  of  a  dial 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  1  the  channel  was  created  as  the  result  of  a  dial 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  snapshot_is_dialed ( struct  ast_channel_snapshot  * snapshot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ( ast_test_flag ( & snapshot - > flags ,  AST_FLAG_OUTGOING ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  ! ( ast_test_flag ( & snapshot - > flags ,  AST_FLAG_ORIGINATED ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Given  two  CDR  snapshots ,  figure  out  who  should  be  Party  A  for  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  resulting  CDR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  left  One  of  the  snapshots 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  right  The  other  snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  The  snapshot  that  won 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  cdr_object_snapshot  * cdr_object_pick_party_a ( struct  cdr_object_snapshot  * left ,  struct  cdr_object_snapshot  * right )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check whether or not the party is dialed. A dialed party is never the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Party  A  with  a  party  that  was  not  dialed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! snapshot_is_dialed ( left - > snapshot )  & &  snapshot_is_dialed ( right - > snapshot ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( snapshot_is_dialed ( left - > snapshot )  & &  ! snapshot_is_dialed ( right - > snapshot ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Try the Party A flag */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( left ,  AST_CDR_FLAG_PARTY_A )  & &  ! ast_test_flag ( right ,  AST_CDR_FLAG_PARTY_A ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! ast_test_flag ( right ,  AST_CDR_FLAG_PARTY_A )  & &  ast_test_flag ( right ,  AST_CDR_FLAG_PARTY_A ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Neither party is dialed and neither has the Party A flag - defer to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  creation  time  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( left - > snapshot - > creationtime . tv_sec  <  right - > snapshot - > creationtime . tv_sec )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( left - > snapshot - > creationtime . tv_sec  >  right - > snapshot - > creationtime . tv_sec )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( left - > snapshot - > creationtime . tv_usec  >  right - > snapshot - > creationtime . tv_usec )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  right ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Okay, fine, take the left one */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Compute  the  duration  for  a  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  long  cdr_object_get_duration ( struct  cdr_object  * cdr )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ( long ) ( ast_tvdiff_ms ( ast_tvzero ( cdr - > end )  ?  ast_tvnow ( )  :  cdr - > end ,  cdr - > start )  /  1000 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Compute  the  billsec  for  a  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  long  cdr_object_get_billsec ( struct  cdr_object  * cdr )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									long  int  ms ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_tvzero ( cdr - > answer ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ms  =  ast_tvdiff_ms ( ast_tvzero ( cdr - > end )  ?  ast_tvnow ( )  :  cdr - > end ,  cdr - > answer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_INITIATED_SECONDS ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ( ms  %  1000  > =  500 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ms  =  ( ms  /  1000 )  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ms  =  ms  /  1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ms ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Set  a  variable  on  a  CDR  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  headp  The  header  pointer  to  the  variable  to  set 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  name  The  name  of  the  variable 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  value  The  value  of  the  variable 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  set_variable ( struct  varshead  * headp ,  const  char  * name ,  const  char  * value )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_var_t  * newvariable ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_BEGIN ( headp ,  newvariable ,  entries )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( ast_var_name ( newvariable ) ,  name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_LIST_REMOVE_CURRENT ( entries ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_var_delete ( newvariable ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE_SAFE_END ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-06 08:36:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( value  & &  ( newvariable  =  ast_var_assign ( name ,  value ) ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_LIST_INSERT_HEAD ( headp ,  newvariable ,  entries ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Create  a  chain  of  \ ref  ast_cdr  objects  from  a  chain  of  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  suitable  for  consumption  by  the  registered  CDR  backends 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr  The  \ ref  cdr_object  to  convert  to  a  public  record 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  A  chain  of  \ ref  ast_cdr  objects  on  success 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  NULL  on  failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  ast_cdr  * cdr_object_create_public_records ( struct  cdr_object  * cdr )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 12:28:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_cdr  * pub_cdr  =  NULL ,  * cdr_prev  =  NULL ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_var_t  * it_var ,  * it_copy_var ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * party_a ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * party_b ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  ast_cdr  * cdr_copy ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Don't create records for CDRs where the party A was a dialed channel */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( snapshot_is_dialed ( it_cdr - > party_a . snapshot )  & &  ! it_cdr - > party_b . snapshot )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " CDR for %s is dialed and has no Party B; discarding \n " , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												it_cdr - > party_a . snapshot - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_copy  =  ast_calloc ( 1 ,  sizeof ( * cdr_copy ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! cdr_copy )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_free ( pub_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										party_a  =  it_cdr - > party_a . snapshot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										party_b  =  it_cdr - > party_b . snapshot ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Party A */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_assert ( party_a  ! =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( cdr_copy - > accountcode ,  party_a - > accountcode ,  sizeof ( cdr_copy - > accountcode ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_copy - > amaflags  =  party_a - > amaflags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( cdr_copy - > channel ,  party_a - > name ,  sizeof ( cdr_copy - > channel ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_callerid_merge ( cdr_copy - > clid ,  sizeof ( cdr_copy - > clid ) ,  party_a - > caller_name ,  party_a - > caller_number ,  " " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( cdr_copy - > src ,  party_a - > caller_number ,  sizeof ( cdr_copy - > src ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( cdr_copy - > uniqueid ,  party_a - > uniqueid ,  sizeof ( cdr_copy - > uniqueid ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( cdr_copy - > lastapp ,  it_cdr - > appl ,  sizeof ( cdr_copy - > lastapp ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( cdr_copy - > lastdata ,  it_cdr - > data ,  sizeof ( cdr_copy - > lastdata ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												main/cdrs: Preserve context/extension when executing a Macro or GoSub
The context/extension in a CDR is generally considered the destination of a
call. When looking at a 2-party call CDR, users will typically be presented
with the following:
context    exten      channel     dest_channel app  data
default    1000       SIP/8675309 SIP/1000     Dial SIP/1000,,20
However, if the Dial actually takes place in a Macro, the current behaviour
in 12 will result in the following CDR:
context    exten      channel     dest_channel app  data
macro-dial s          SIP/8675309 SIP/1000     Dial SIP/1000,,20
The same is true of a GoSub:
context    exten      channel     dest_channel app  data
subs       dial_stuff SIP/8675309 SIP/1000     Dial SIP/1000,,20
This generally makes the context/exten fields less than useful.
It isn't hard to preserve these values in the CDR state machine; however, we
need to have something that informs us when a channel is executing a
subroutine. Prior to this patch, there isn't anything that does this.
This patch solves this problem by adding a new channel flag,
AST_FLAG_SUBROUTINE_EXEC. This flag is set on a channel when it executes a
Macro or a GoSub. The CDR engine looks for this value when updating a Party A
snapshot; if the flag is present, we don't override the context/exten on the
main CDR object. In a funny quirk, executing a hangup handler must *not* abide
by this logic, as the endbeforehexten logic assumes that the user wants to see
data that occurs in hangup logic, which includes those subroutines. Since
those execute outside of a typical Dial operation (and will typically have
their own dedicated CDR anyway), this is unlikely to cause any heartburn.
Review: https://reviewboard.asterisk.org/r/3962/
ASTERISK-24254 #close
Reported by: tm1000, Tony Lewis
Tested by: Tony Lewis
........
Merged revisions 422718 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 422719 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@422720 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-09-05 22:04:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( cdr_copy - > dst ,  it_cdr - > exten ,  sizeof ( cdr_copy - > dst ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( cdr_copy - > dcontext ,  it_cdr - > context ,  sizeof ( cdr_copy - > dcontext ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Party B */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( party_b )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_copy_string ( cdr_copy - > dstchannel ,  party_b - > name ,  sizeof ( cdr_copy - > dstchannel ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_copy_string ( cdr_copy - > peeraccount ,  party_b - > accountcode ,  sizeof ( cdr_copy - > peeraccount ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! ast_strlen_zero ( it_cdr - > party_b . userfield ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												snprintf ( cdr_copy - > userfield ,  sizeof ( cdr_copy - > userfield ) ,  " %s;%s " ,  it_cdr - > party_a . userfield ,  it_cdr - > party_b . userfield ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ast_strlen_zero ( cdr_copy - > userfield )  & &  ! ast_strlen_zero ( it_cdr - > party_a . userfield ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_copy_string ( cdr_copy - > userfield ,  it_cdr - > party_a . userfield ,  sizeof ( cdr_copy - > userfield ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Timestamps/durations */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_copy - > start  =  it_cdr - > start ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_copy - > answer  =  it_cdr - > answer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_copy - > end  =  it_cdr - > end ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_copy - > billsec  =  cdr_object_get_billsec ( it_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_copy - > duration  =  cdr_object_get_duration ( it_cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Flags and IDs */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_flags ( cdr_copy ,  & it_cdr - > flags ,  AST_FLAGS_ALL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( cdr_copy - > linkedid ,  it_cdr - > linkedid ,  sizeof ( cdr_copy - > linkedid ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_copy - > disposition  =  it_cdr - > disposition ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_copy - > sequence  =  it_cdr - > sequence ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Variables */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										copy_variables ( & cdr_copy - > varshead ,  & it_cdr - > party_a . variables ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_LIST_TRAVERSE ( & it_cdr - > party_b . variables ,  it_var ,  entries )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											int  found  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-06 08:36:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											struct  ast_var_t  * newvariable ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_LIST_TRAVERSE ( & cdr_copy - > varshead ,  it_copy_var ,  entries )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:38:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( ! strcasecmp ( ast_var_name ( it_var ) ,  ast_var_name ( it_copy_var ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													found  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-06 08:36:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! found  & &  ( newvariable  =  ast_var_assign ( ast_var_name ( it_var ) ,  ast_var_value ( it_var ) ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AST_LIST_INSERT_TAIL ( & cdr_copy - > varshead ,  newvariable ,  entries ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! pub_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pub_cdr  =  cdr_copy ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_prev  =  pub_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_prev - > next  =  cdr_copy ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_prev  =  cdr_copy ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  pub_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Dispatch  a  CDR . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr  The  \ ref  cdr_object  to  dispatch 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  will  create  a  \ ref  ast_cdr  object  and  publish  it  to  the  various  backends 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_dispatch ( struct  cdr_object  * cdr )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_cdr  * pub_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									CDR_DEBUG ( mod_cfg ,  " %p - Dispatching CDR for Party A %s, Party B %s \n " ,  cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr - > party_a . snapshot - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr - > party_b . snapshot  ?  cdr - > party_b . snapshot - > name  :  " <none> " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pub_cdr  =  cdr_object_create_public_records ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_detach ( pub_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Set  the  disposition  on  a  \ ref  cdr_object  based  on  a  hangupcause  code 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr  The  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  hangupcause  The  Asterisk  hangup  cause  code 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_set_disposition ( struct  cdr_object  * cdr ,  int  hangupcause )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Change the disposition based on the hang up cause */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( hangupcause )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_CAUSE_BUSY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr - > disposition  =  AST_CDR_BUSY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_CAUSE_CONGESTION : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_CONGESTION ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr - > disposition  =  AST_CDR_FAILED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr - > disposition  =  AST_CDR_CONGESTION ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_CAUSE_NO_ROUTE_DESTINATION : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_CAUSE_UNREGISTERED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr - > disposition  =  AST_CDR_FAILED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_CAUSE_NORMAL_CLEARING : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  AST_CAUSE_NO_ANSWER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr - > disposition  =  AST_CDR_NOANSWER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Finalize  a  CDR . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  function  is  safe  to  call  multiple  times .  Note  that  you  can  call  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  explicitly  before  going  to  the  finalized  state  if  there ' s  a  chance  the  CDR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  will  be  re - activated ,  in  which  case  the  \ ref  cdr_object ' s  end  time  should  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  cleared .  This  function  is  implicitly  called  when  a  CDR  transitions  to  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  finalized  state  and  right  before  it  is  dispatched 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr_object  The  CDR  to  finalize 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_finalize ( struct  cdr_object  * cdr )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_tvzero ( cdr - > end ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr - > end  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr - > disposition  = =  AST_CDR_NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ast_tvzero ( cdr - > answer ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr - > disposition  =  AST_CDR_ANSWERED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( cdr - > party_a . snapshot - > hangupcause )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_set_disposition ( cdr ,  cdr - > party_a . snapshot - > hangupcause ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( cdr - > party_b . snapshot  & &  cdr - > party_b . snapshot - > hangupcause )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_set_disposition ( cdr ,  cdr - > party_b . snapshot - > hangupcause ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr - > disposition  =  AST_CDR_FAILED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 18:58:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* tv_usec is suseconds_t, which could be int or long */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dispo %s \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											cdr - > party_a . snapshot - > name , 
							 
						 
					
						
							
								
									
										
										
										
											2015-03-23 00:05:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											( long ) cdr - > start . tv_sec , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 18:58:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											( long ) cdr - > start . tv_usec , 
							 
						 
					
						
							
								
									
										
										
										
											2015-03-23 00:05:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											( long ) cdr - > answer . tv_sec , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 18:58:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											( long ) cdr - > answer . tv_usec , 
							 
						 
					
						
							
								
									
										
										
										
											2015-03-23 00:05:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											( long ) cdr - > end . tv_sec , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 18:58:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											( long ) cdr - > end . tv_usec , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_cdr_disp2str ( cdr - > disposition ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Check  to  see  if  a  CDR  needs  to  move  to  the  finalized  state  because 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  its  Party  A  hungup . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_check_party_a_hangup ( struct  cdr_object  * cdr )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_END_BEFORE_H_EXTEN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ast_test_flag ( & cdr - > party_a . snapshot - > softhangup_flags ,  AST_SOFTHANGUP_HANGUP_EXEC ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_finalize ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & cdr - > party_a . snapshot - > flags ,  AST_FLAG_DEAD ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  cdr - > fn_table  ! =  & finalized_state_fn_table )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_transition_state ( cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Check  to  see  if  a  CDR  needs  to  be  answered  based  on  its  Party  A . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Note  that  this  is  safe  to  call  as  much  as  you  want  -  we  won ' t  answer  twice 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_check_party_a_answer ( struct  cdr_object  * cdr )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr - > party_a . snapshot - > state  = =  AST_STATE_UP  & &  ast_tvzero ( cdr - > answer ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr - > answer  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 18:58:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* tv_usec is suseconds_t, which could be int or long */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										CDR_DEBUG ( mod_cfg ,  " %p - Set answered time to %ld.%06ld \n " ,  cdr , 
							 
						 
					
						
							
								
									
										
										
										
											2015-03-23 00:05:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											( long ) cdr - > answer . tv_sec , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 18:58:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											( long ) cdr - > answer . tv_usec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* \brief Set Caller ID information on a CDR */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_update_cid ( struct  cdr_object_snapshot  * old_snapshot ,  struct  ast_channel_snapshot  * new_snapshot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! old_snapshot - > snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_variable ( & old_snapshot - > variables ,  " dnid " ,  new_snapshot - > caller_dnid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_variable ( & old_snapshot - > variables ,  " callingsubaddr " ,  new_snapshot - > caller_subaddr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_variable ( & old_snapshot - > variables ,  " calledsubaddr " ,  new_snapshot - > dialed_subaddr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! strcmp ( old_snapshot - > snapshot - > caller_dnid ,  new_snapshot - > caller_dnid ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_variable ( & old_snapshot - > variables ,  " dnid " ,  new_snapshot - > caller_dnid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! strcmp ( old_snapshot - > snapshot - > caller_subaddr ,  new_snapshot - > caller_subaddr ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_variable ( & old_snapshot - > variables ,  " callingsubaddr " ,  new_snapshot - > caller_subaddr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! strcmp ( old_snapshot - > snapshot - > dialed_subaddr ,  new_snapshot - > dialed_subaddr ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_variable ( & old_snapshot - > variables ,  " calledsubaddr " ,  new_snapshot - > dialed_subaddr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Swap  an  old  \ ref  cdr_object_snapshot ' s  \ ref  ast_channel_snapshot  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  a  new  \ ref  ast_channel_snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  old_snapshot  The  old  \ ref  cdr_object_snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  new_snapshot  The  new  \ ref  ast_channel_snapshot  for  old_snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_swap_snapshot ( struct  cdr_object_snapshot  * old_snapshot ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_channel_snapshot  * new_snapshot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_update_cid ( old_snapshot ,  new_snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( old_snapshot - > snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_t_ref ( old_snapshot - > snapshot ,  - 1 ,  " Drop ref for swap " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_t_ref ( new_snapshot ,  + 1 ,  " Bump ref for swap " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									old_snapshot - > snapshot  =  new_snapshot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* BASE METHOD IMPLEMENTATIONS */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  base_process_party_a ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_assert ( strcasecmp ( snapshot - > name ,  cdr - > party_a . snapshot - > name )  = =  0 ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-01-02 10:23:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Finalize the CDR if we're in hangup logic and we're set to do so */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & snapshot - > softhangup_flags ,  AST_SOFTHANGUP_HANGUP_EXEC ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-02 10:23:39 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										& &  ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_END_BEFORE_H_EXTEN ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_finalize ( cdr ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												main/cdrs: Preserve context/extension when executing a Macro or GoSub
The context/extension in a CDR is generally considered the destination of a
call. When looking at a 2-party call CDR, users will typically be presented
with the following:
context    exten      channel     dest_channel app  data
default    1000       SIP/8675309 SIP/1000     Dial SIP/1000,,20
However, if the Dial actually takes place in a Macro, the current behaviour
in 12 will result in the following CDR:
context    exten      channel     dest_channel app  data
macro-dial s          SIP/8675309 SIP/1000     Dial SIP/1000,,20
The same is true of a GoSub:
context    exten      channel     dest_channel app  data
subs       dial_stuff SIP/8675309 SIP/1000     Dial SIP/1000,,20
This generally makes the context/exten fields less than useful.
It isn't hard to preserve these values in the CDR state machine; however, we
need to have something that informs us when a channel is executing a
subroutine. Prior to this patch, there isn't anything that does this.
This patch solves this problem by adding a new channel flag,
AST_FLAG_SUBROUTINE_EXEC. This flag is set on a channel when it executes a
Macro or a GoSub. The CDR engine looks for this value when updating a Party A
snapshot; if the flag is present, we don't override the context/exten on the
main CDR object. In a funny quirk, executing a hangup handler must *not* abide
by this logic, as the endbeforehexten logic assumes that the user wants to see
data that occurs in hangup logic, which includes those subroutines. Since
those execute outside of a typical Dial operation (and will typically have
their own dedicated CDR anyway), this is unlikely to cause any heartburn.
Review: https://reviewboard.asterisk.org/r/3962/
ASTERISK-24254 #close
Reported by: tm1000, Tony Lewis
Tested by: Tony Lewis
........
Merged revisions 422718 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 422719 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@422720 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-09-05 22:04:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Only  record  the  context  and  extension  if  we  aren ' t  in  a  subroutine ,  or  if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  we  are  executing  hangup  logic . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_test_flag ( & snapshot - > flags ,  AST_FLAG_SUBROUTINE_EXEC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ast_test_flag ( & snapshot - > softhangup_flags ,  AST_SOFTHANGUP_HANGUP_EXEC ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_string_field_set ( cdr ,  context ,  snapshot - > context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_string_field_set ( cdr ,  exten ,  snapshot - > exten ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-02-03 01:31:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr_object_swap_snapshot ( & cdr - > party_a ,  snapshot ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* When Party A is originated to an application and the application exits, the stack
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  will  attempt  to  clear  the  application  and  restore  the  dummy  originate  application 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  of  " AppDialX " .  Prevent  that ,  and  any  other  application  changes  we  might  not  want 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  here . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_strlen_zero ( snapshot - > appl ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  ( strncasecmp ( snapshot - > appl ,  " appdial " ,  7 )  | |  ast_strlen_zero ( cdr - > appl ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  ! ast_test_flag ( & cdr - > flags ,  AST_CDR_LOCK_APP ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_string_field_set ( cdr ,  appl ,  snapshot - > appl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_string_field_set ( cdr ,  data ,  snapshot - > data ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Dial (app_dial) is a special case. Because pre-dial handlers, which
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  execute  before  the  dial  begins ,  will  alter  the  application / data  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  something  people  typically  don ' t  want  to  see ,  if  we  see  a  channel  enter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  into  Dial  here ,  we  set  the  appl / data  accordingly  and  lock  it . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcmp ( snapshot - > appl ,  " Dial " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_set_flag ( & cdr - > flags ,  AST_CDR_LOCK_APP ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( cdr ,  linkedid ,  snapshot - > linkedid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_check_party_a_answer ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_check_party_a_hangup ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  base_process_bridge_leave ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2016-07-11 19:07:20 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  base_process_dial_end ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer ,  const  char  * dial_status )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  process_bridge_enter_results  base_process_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Base process bridge enter simply indicates that we can't handle it */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  BRIDGE_ENTER_NEED_CDR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  base_process_parked_channel ( struct  cdr_object  * cdr ,  struct  ast_parked_call_payload  * parking_info )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  park_info [ 128 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_assert ( ! strcasecmp ( parking_info - > parkee - > name ,  cdr - > party_a . snapshot - > name ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Update Party A information regardless */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr - > fn_table - > process_party_a ( cdr ,  parking_info - > parkee ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Fake out where we're parked */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( cdr ,  appl ,  " Park " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									snprintf ( park_info ,  sizeof ( park_info ) ,  " %s:%u " ,  parking_info - > parkinglot ,  parking_info - > parkingspace ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( cdr ,  data ,  park_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Prevent any further changes to the App/Data fields for this record */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_set_flag ( & cdr - > flags ,  AST_CDR_LOCK_APP ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* SINGLE STATE */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  single_state_init_function ( struct  cdr_object  * cdr )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr - > start  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_check_party_a_answer ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  single_state_process_party_b ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* This should never happen! */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( cdr - > party_b . snapshot  = =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  single_state_process_dial_begin ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( caller  & &  ! strcasecmp ( cdr - > party_a . snapshot - > name ,  caller - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-02-03 01:31:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										base_process_party_a ( cdr ,  caller ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										CDR_DEBUG ( mod_cfg ,  " %p - Updated Party A %s snapshot \n " ,  cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr - > party_a . snapshot - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_swap_snapshot ( & cdr - > party_b ,  peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										CDR_DEBUG ( mod_cfg ,  " %p - Updated Party B %s snapshot \n " ,  cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr - > party_b . snapshot - > name ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If we have two parties, lock the application that caused the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  two  parties  to  be  associated .  This  prevents  mid - call  event 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  macros / gosubs  from  perturbing  the  CDR  application / data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_set_flag ( & cdr - > flags ,  AST_CDR_LOCK_APP ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( cdr - > party_a . snapshot - > name ,  peer - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* We're the entity being dialed, i.e., outbound origination */ 
							 
						 
					
						
							
								
									
										
										
										
											2014-02-03 01:31:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										base_process_party_a ( cdr ,  peer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										CDR_DEBUG ( mod_cfg ,  " %p - Updated Party A %s snapshot \n " ,  cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr - > party_a . snapshot - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & dial_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Handle  a  comparison  between  our  \ ref  cdr_object  and  a  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  already  in  the  bridge  while  in  the  Single  state .  The  goal  of  this  is  to  find 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  a  Party  B  for  our  CDR . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr  Our  \ ref  cdr_object  in  the  Single  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cand_cdr  The  \ ref  cdr_object  already  in  the  Bridge  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  0  The  cand_cdr  had  a  Party  A  or  Party  B  that  we  could  use  as  our 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Party  B 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  1  No  party  in  the  cand_cdr  could  be  used  as  our  Party  B 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  single_state_bridge_enter_comparison ( struct  cdr_object  * cdr ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  cdr_object  * cand_cdr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object_snapshot  * party_a ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Don't match on ourselves */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! strcasecmp ( cdr - > party_a . snapshot - > name ,  cand_cdr - > party_a . snapshot - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Try the candidate CDR's Party A first */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									party_a  =  cdr_object_pick_party_a ( & cdr - > party_a ,  & cand_cdr - > party_a ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! strcasecmp ( party_a - > snapshot - > name ,  cdr - > party_a . snapshot - > name ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										CDR_DEBUG ( mod_cfg ,  " %p - Party A %s has new Party B %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr ,  cdr - > party_a . snapshot - > name ,  cand_cdr - > party_a . snapshot - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_object_snapshot_copy ( & cdr - > party_b ,  & cand_cdr - > party_a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! cand_cdr - > party_b . snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* We just stole them - finalize their CDR. Note that this won't
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  transition  their  state ,  it  just  sets  the  end  time  and  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  disposition  -  if  we  need  to  re - activate  them  later ,  we  can . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_finalize ( cand_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Try their Party B, unless it's us */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cand_cdr - > party_b . snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ! strcasecmp ( cdr - > party_a . snapshot - > name ,  cand_cdr - > party_b . snapshot - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									party_a  =  cdr_object_pick_party_a ( & cdr - > party_a ,  & cand_cdr - > party_b ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! strcasecmp ( party_a - > snapshot - > name ,  cdr - > party_a . snapshot - > name ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										CDR_DEBUG ( mod_cfg ,  " %p - Party A %s has new Party B %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr ,  cdr - > party_a . snapshot - > name ,  cand_cdr - > party_b . snapshot - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_object_snapshot_copy ( & cdr - > party_b ,  & cand_cdr - > party_b ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  process_bridge_enter_results  single_state_process_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel )  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ao2_iterator  it_cdrs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * channel_id ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  success  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( cdr ,  bridge ,  bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ao2_container_count ( bridge - > channels )  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* No one in the bridge yet but us! */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_object_transition_state ( cdr ,  & bridge_state_fn_table ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  BRIDGE_ENTER_ONLY_PARTY ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( it_cdrs  =  ao2_iterator_init ( bridge - > channels ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										! success  & &  ( channel_id  =  ao2_iterator_next ( & it_cdrs ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( channel_id ,  - 1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RAII_VAR ( struct  cdr_object  * ,  cand_cdr_master , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_find ( active_cdrs_by_channel ,  channel_id ,  OBJ_KEY ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  cdr_object  * cand_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! cand_cdr_master )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_lock ( cand_cdr_master ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  ( cand_cdr  =  cand_cdr_master ;  cand_cdr ;  cand_cdr  =  cand_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Skip any records that are not in a bridge or in this bridge.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  I ' m  not  sure  how  that  would  happen ,  but  it  pays  to  be  careful .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( cand_cdr - > fn_table  ! =  & bridge_state_fn_table  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													strcmp ( cdr - > bridge ,  cand_cdr - > bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( single_state_bridge_enter_comparison ( cdr ,  cand_cdr ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* We successfully got a party B - break out */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											success  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_unlock ( cand_cdr_master ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & it_cdrs ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* We always transition state, even if we didn't get a peer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & bridge_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Success implies that we have a Party B */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( success )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  BRIDGE_ENTER_OBTAINED_PARTY_B ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  BRIDGE_ENTER_NO_PARTY_B ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  single_state_process_parking_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & parked_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* DIAL STATE */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  dial_state_process_party_b ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( snapshot  ! =  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr - > party_b . snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  strcasecmp ( cdr - > party_b . snapshot - > name ,  snapshot - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_swap_snapshot ( & cdr - > party_b ,  snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If party B hangs up, finalize this CDR */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & cdr - > party_b . snapshot - > flags ,  AST_FLAG_DEAD ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_object_transition_state ( cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  dial_state_process_dial_begin ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Don't process a begin dial here. A party A already in the dial state will
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  who  receives  a  dial  begin  for  something  else  will  be  handled  by  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  message  router  callback  and  will  add  a  new  CDR  for  the  party  A  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-16 17:33:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Convert  a  dial  status  to  a  CDR  disposition 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  ast_cdr_disposition  dial_status_to_disposition ( const  char  * dial_status )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! strcmp ( dial_status ,  " ANSWER " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_CDR_ANSWERED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcmp ( dial_status ,  " BUSY " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_CDR_BUSY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcmp ( dial_status ,  " CANCEL " )  | |  ! strcmp ( dial_status ,  " NOANSWER " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_CDR_NOANSWER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcmp ( dial_status ,  " CONGESTION " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_CONGESTION ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  AST_CDR_FAILED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  AST_CDR_CONGESTION ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcmp ( dial_status ,  " FAILED " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  AST_CDR_FAILED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  AST_CDR_FAILED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  dial_state_process_dial_end ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer ,  const  char  * dial_status )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * party_a ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( caller )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										party_a  =  caller ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										party_a  =  peer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_assert ( ! strcasecmp ( cdr - > party_a . snapshot - > name ,  party_a - > name ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr_object_swap_snapshot ( & cdr - > party_a ,  party_a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr - > party_b . snapshot )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( strcasecmp ( cdr - > party_b . snapshot - > name ,  peer - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* Not the status for this CDR - defer back to the message router */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_swap_snapshot ( & cdr - > party_b ,  peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Set the disposition based on the dial string. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr - > disposition  =  dial_status_to_disposition ( dial_status ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr - > disposition  = =  AST_CDR_ANSWERED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Switch to dial pending to wait and see what the caller does */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_transition_state ( cdr ,  & dialed_pending_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_transition_state ( cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  process_bridge_enter_results  dial_state_process_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel )  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ao2_iterator  it_cdrs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * channel_id ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  success  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( cdr ,  bridge ,  bridge - > uniqueid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get parties in the bridge */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ao2_container_count ( bridge - > channels )  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* No one in the bridge yet but us! */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_object_transition_state ( cdr ,  & bridge_state_fn_table ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  BRIDGE_ENTER_ONLY_PARTY ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( it_cdrs  =  ao2_iterator_init ( bridge - > channels ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										! success  & &  ( channel_id  =  ao2_iterator_next ( & it_cdrs ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( channel_id ,  - 1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RAII_VAR ( struct  cdr_object  * ,  cand_cdr_master , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_find ( active_cdrs_by_channel ,  channel_id ,  OBJ_KEY ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  cdr_object  * cand_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! cand_cdr_master )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_lock ( cand_cdr_master ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  ( cand_cdr  =  cand_cdr_master ;  cand_cdr ;  cand_cdr  =  cand_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Skip any records that are not in a bridge or in this bridge.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  I ' m  not  sure  how  that  would  happen ,  but  it  pays  to  be  careful .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( cand_cdr - > fn_table  ! =  & bridge_state_fn_table  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													strcmp ( cdr - > bridge ,  cand_cdr - > bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 17:31:33 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* If we don't have a Party B (originated channel), skip it */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! cdr - > party_b . snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* Skip any records that aren't our Party B */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( strcasecmp ( cdr - > party_b . snapshot - > name ,  cand_cdr - > party_a . snapshot - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_snapshot_copy ( & cdr - > party_b ,  & cand_cdr - > party_a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If they have a Party B, they joined up with someone else as their
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  Party  A .  Don ' t  finalize  them  as  they ' re  active .  Otherwise ,  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  have  stolen  them  so  they  need  to  be  finalized . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! cand_cdr - > party_b . snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr_object_finalize ( cand_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											success  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_unlock ( cand_cdr_master ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & it_cdrs ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* We always transition state, even if we didn't get a peer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & bridge_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Success implies that we have a Party B */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( success )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  BRIDGE_ENTER_OBTAINED_PARTY_B ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  BRIDGE_ENTER_NO_PARTY_B ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* DIALED PENDING STATE */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  dialed_pending_state_process_party_a ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If we get a CEP change, we're executing dialplan. If we have a Party B
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  that  means  we  need  a  new  CDR ;  otherwise ,  switch  us  over  to  single . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( snapshot_cep_changed ( cdr - > party_a . snapshot ,  snapshot ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( cdr - > party_b . snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_transition_state ( cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr - > fn_table - > process_party_a ( cdr ,  snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_transition_state ( cdr ,  & single_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr - > fn_table - > process_party_a ( cdr ,  snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									base_process_party_a ( cdr ,  snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  enum  process_bridge_enter_results  dialed_pending_state_process_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel )  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & dial_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cdr - > fn_table - > process_bridge_enter ( cdr ,  bridge ,  channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  dialed_pending_state_process_parking_bridge_enter ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel )  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-09-28 20:55:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cdr - > party_b . snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We can't handle this as we have a Party B - ask for a new one */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & parked_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  dialed_pending_state_process_dial_begin ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * caller ,  struct  ast_channel_snapshot  * peer )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Ask for a new CDR */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* BRIDGE STATE */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_state_process_party_b ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr - > party_b . snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  strcasecmp ( cdr - > party_b . snapshot - > name ,  snapshot - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_swap_snapshot ( & cdr - > party_b ,  snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If party B hangs up, finalize this CDR */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & cdr - > party_b . snapshot - > flags ,  AST_FLAG_DEAD ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_object_transition_state ( cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  bridge_state_process_bridge_leave ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( strcmp ( cdr - > bridge ,  bridge - > uniqueid ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( strcasecmp ( cdr - > party_a . snapshot - > name ,  channel - > name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  cdr - > party_b . snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  strcasecmp ( cdr - > party_b . snapshot - > name ,  channel - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* PARKED STATE */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  parked_state_process_bridge_leave ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge ,  struct  ast_channel_snapshot  * channel )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( strcasecmp ( cdr - > party_a . snapshot - > name ,  channel - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* FINALIZED STATE */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  finalized_state_init_function ( struct  cdr_object  * cdr )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_finalize ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  finalized_state_process_party_a ( struct  cdr_object  * cdr ,  struct  ast_channel_snapshot  * snapshot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & snapshot - > softhangup_flags ,  AST_SOFTHANGUP_HANGUP_EXEC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_END_BEFORE_H_EXTEN ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Indicate that, if possible, we should get a new CDR */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 23:22:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Filter  channel  snapshots  by  technology 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  filter_channel_snapshot ( struct  ast_channel_snapshot  * snapshot )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  snapshot - > tech_properties  &  AST_CHAN_TP_INTERNAL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Filter  a  channel  cache  update 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  filter_channel_cache_message ( struct  ast_channel_snapshot  * old_snapshot ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_channel_snapshot  * new_snapshot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ret  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Drop cache updates from certain channel technologies */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( old_snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ret  | =  filter_channel_snapshot ( old_snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( new_snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ret  | =  filter_channel_snapshot ( new_snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-09 15:00:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  dial_status_end ( const  char  * dialstatus )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ( strcmp ( dialstatus ,  " RINGING " )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											strcmp ( dialstatus ,  " PROCEEDING " )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											strcmp ( dialstatus ,  " PROGRESS " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* TOPIC ROUTER CALLBACKS */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Handler  for  Stasis - Core  dial  messages 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  Passed  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sub  The  stasis  subscription  for  this  message  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  topic  The  topic  this  message  was  published  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  message  The  message 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Multiple revisions 399887,400138,400178,400180-400181
........
  r399887 | dlee | 2013-09-26 10:41:47 -0500 (Thu, 26 Sep 2013) | 1 line
  
  Minor performance bump by not allocate manager variable struct if we don't need it
........
  r400138 | dlee | 2013-09-30 10:24:00 -0500 (Mon, 30 Sep 2013) | 23 lines
  
  Stasis performance improvements
  
  This patch addresses several performance problems that were found in
  the initial performance testing of Asterisk 12.
  
  The Stasis dispatch object was allocated as an AO2 object, even though
  it has a very confined lifecycle. This was replaced with a straight
  ast_malloc().
  
  The Stasis message router was spending an inordinate amount of time
  searching hash tables. In this case, most of our routers had 6 or
  fewer routes in them to begin with. This was replaced with an array
  that's searched linearly for the route.
  
  We more heavily rely on AO2 objects in Asterisk 12, and the memset()
  in ao2_ref() actually became noticeable on the profile. This was
  #ifdef'ed to only run when AO2_DEBUG was enabled.
  
  After being misled by an erroneous comment in taskprocessor.c during
  profiling, the wrong comment was removed.
  
  Review: https://reviewboard.asterisk.org/r/2873/
........
  r400178 | dlee | 2013-09-30 13:26:27 -0500 (Mon, 30 Sep 2013) | 24 lines
  
  Taskprocessor optimization; switch Stasis to use taskprocessors
  
  This patch optimizes taskprocessor to use a semaphore for signaling,
  which the OS can do a better job at managing contention and waiting
  that we can with a mutex and condition.
  
  The taskprocessor execution was also slightly optimized to reduce the
  number of locks taken.
  
  The only observable difference in the taskprocessor implementation is
  that when the final reference to the taskprocessor goes away, it will
  execute all tasks to completion instead of discarding the unexecuted
  tasks.
  
  For systems where unnamed semaphores are not supported, a really
  simple semaphore implementation is provided. (Which gives identical
  performance as the original taskprocessor implementation).
  
  The way we ended up implementing Stasis caused the threadpool to be a
  burden instead of a boost to performance. This was switched to just
  use taskprocessors directly for subscriptions.
  
  Review: https://reviewboard.asterisk.org/r/2881/
........
  r400180 | dlee | 2013-09-30 13:39:34 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Optimize how Stasis forwards are dispatched
  
  This patch optimizes how forwards are dispatched in Stasis.
  
  Originally, forwards were dispatched as subscriptions that are invoked
  on the publishing thread. This did not account for the vast number of
  forwards we would end up having in the system, and the amount of work it
  would take to walk though the forward subscriptions.
  
  This patch modifies Stasis so that rather than walking the tree of
  forwards on every dispatch, when forwards and subscriptions are changed,
  the subscriber list for every topic in the tree is changed.
  
  This has a couple of benefits. First, this reduces the workload of
  dispatching messages. It also reduces contention when dispatching to
  different topics that happen to forward to the same aggregation topic
  (as happens with all of the channel, bridge and endpoint topics).
  
  Since forwards are no longer subscriptions, the bulk of this patch is
  simply changing stasis_subscription objects to stasis_forward objects
  (which, admittedly, I should have done in the first place.)
  
  Since this required me to yet again put in a growing array, I finally
  abstracted that out into a set of ast_vector macros in
  asterisk/vector.h.
  
  Review: https://reviewboard.asterisk.org/r/2883/
........
  r400181 | dlee | 2013-09-30 13:48:57 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Remove dispatch object allocation from Stasis publishing
  
  While looking for areas for performance improvement, I realized that an
  unused feature in Stasis was negatively impacting performance.
  
  When a message is sent to a subscriber, a dispatch object is allocated
  for the dispatch, containing the topic the message was published to, the
  subscriber the message is being sent to, and the message itself.
  
  The topic is actually unused by any subscriber in Asterisk today. And
  the subscriber is associated with the taskprocessor the message is being
  dispatched to.
  
  First, this patch removes the unused topic parameter from Stasis
  subscription callbacks.
  
  Second, this patch introduces the concept of taskprocessor local data,
  data that may be set on a taskprocessor and provided along with the data
  pointer when a task is pushed using the ast_taskprocessor_push_local()
  call. This allows the task to have both data specific to that
  taskprocessor, in addition to data specific to that invocation.
  
  With those two changes, the dispatch object can be removed completely,
  and the message is simply refcounted and sent directly to the
  taskprocessor.
  
  Review: https://reviewboard.asterisk.org/r/2884/
........
Merged revisions 399887,400138,400178,400180-400181 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-30 18:55:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  handle_dial_message ( void  * data ,  struct  stasis_subscription  * sub ,  struct  stasis_message  * message )  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-29 21:37:29 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_multi_channel_blob  * payload  =  stasis_message_data ( message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * caller ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * peer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_json  * dial_status_blob ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * dial_status  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									caller  =  ast_multi_channel_blob_get_channel ( payload ,  " caller " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									peer  =  ast_multi_channel_blob_get_channel ( payload ,  " peer " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! peer  & &  ! caller )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dial_status_blob  =  ast_json_object_get ( ast_multi_channel_blob_get_json ( payload ) ,  " dialstatus " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( dial_status_blob )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dial_status  =  ast_json_string_get ( dial_status_blob ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									CDR_DEBUG ( mod_cfg ,  " Dial %s message for %s, %s: %u.%08u \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_strlen_zero ( dial_status )  ?  " Begin "  :  " End " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											caller  ?  caller - > name  :  " (none) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											peer  ?  peer - > name  :  " (none) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( unsigned  int ) stasis_message_timestamp ( message ) - > tv_sec , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( unsigned  int ) stasis_message_timestamp ( message ) - > tv_usec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 23:22:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( filter_channel_snapshot ( peer )  | |  ( caller  & &  filter_channel_snapshot ( caller ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Figure out who is running this show */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( caller )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr  =  ao2_find ( active_cdrs_by_channel ,  caller - > uniqueid ,  OBJ_KEY ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr  =  ao2_find ( active_cdrs_by_channel ,  peer - > uniqueid ,  OBJ_KEY ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-08 02:58:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_WARNING ,  " No CDR for channel %s \n " ,  caller  ?  caller - > name  :  peer - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-18 15:28:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-08 02:58:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_strlen_zero ( dial_status ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! it_cdr - > fn_table - > process_dial_begin )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											CDR_DEBUG ( mod_cfg ,  " %p - Processing Dial Begin message for channel %s, peer %s \n " , 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													it_cdr , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix FRACK message from external redirects; handle outbound channels better
This patch does the following:
 * It simplifies the Dial handling in CDRs. As a rule, the caller in a dial
   relationship is always the Party A. There was some logic present in the
   handling of the dial message that could, conceivably, pick the caller
   as Party A for the beginning of the dial and the peer as Party A for the
   end of the dial. This shouldn't have happened if the code in the bridging
   framework was doing its job; however, that was broken and it led to the
   FRACK. As it is, this code was overly ocmplex and not needed: the caller,
   if present, should always be Party A. Period.
 * It properly checks to see if a channel will continue on in the dialplan.
   ast_check_hangup - much like cake at the end - is a lie. It will tell
   you that you are hungup when you are not. Do not believe it.
   I would make this function tell the truth, but I'm nervous that we've been
   depending on it sitting on its throne of lies for far too long, and it would
   probably break lots of things. So I'm just checking the "internal" soft
   hangup flags, like everyone else.
(closes issue ASTERISK-22060)
Reported by: Mark Michelson
(issue ASTERISK-21831)
Reported by: Matt Jordan
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394290 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-13 23:28:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													caller  ?  caller - > name  :  " (none) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													peer  ?  peer - > name  :  " (none) " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											res  & =  it_cdr - > fn_table - > process_dial_begin ( it_cdr , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix FRACK message from external redirects; handle outbound channels better
This patch does the following:
 * It simplifies the Dial handling in CDRs. As a rule, the caller in a dial
   relationship is always the Party A. There was some logic present in the
   handling of the dial message that could, conceivably, pick the caller
   as Party A for the beginning of the dial and the peer as Party A for the
   end of the dial. This shouldn't have happened if the code in the bridging
   framework was doing its job; however, that was broken and it led to the
   FRACK. As it is, this code was overly ocmplex and not needed: the caller,
   if present, should always be Party A. Period.
 * It properly checks to see if a channel will continue on in the dialplan.
   ast_check_hangup - much like cake at the end - is a lie. It will tell
   you that you are hungup when you are not. Do not believe it.
   I would make this function tell the truth, but I'm nervous that we've been
   depending on it sitting on its throne of lies for far too long, and it would
   probably break lots of things. So I'm just checking the "internal" soft
   hangup flags, like everyone else.
(closes issue ASTERISK-22060)
Reported by: Mark Michelson
(issue ASTERISK-21831)
Reported by: Matt Jordan
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394290 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-13 23:28:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													caller , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													peer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-09 15:00:56 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( dial_status_end ( dial_status ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! it_cdr - > fn_table - > process_dial_end )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											CDR_DEBUG ( mod_cfg ,  " %p - Processing Dial End message for channel %s, peer %s \n " , 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													it_cdr , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix FRACK message from external redirects; handle outbound channels better
This patch does the following:
 * It simplifies the Dial handling in CDRs. As a rule, the caller in a dial
   relationship is always the Party A. There was some logic present in the
   handling of the dial message that could, conceivably, pick the caller
   as Party A for the beginning of the dial and the peer as Party A for the
   end of the dial. This shouldn't have happened if the code in the bridging
   framework was doing its job; however, that was broken and it led to the
   FRACK. As it is, this code was overly ocmplex and not needed: the caller,
   if present, should always be Party A. Period.
 * It properly checks to see if a channel will continue on in the dialplan.
   ast_check_hangup - much like cake at the end - is a lie. It will tell
   you that you are hungup when you are not. Do not believe it.
   I would make this function tell the truth, but I'm nervous that we've been
   depending on it sitting on its throne of lies for far too long, and it would
   probably break lots of things. So I'm just checking the "internal" soft
   hangup flags, like everyone else.
(closes issue ASTERISK-22060)
Reported by: Mark Michelson
(issue ASTERISK-21831)
Reported by: Matt Jordan
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394290 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-13 23:28:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													caller  ?  caller - > name  :  " (none) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													peer  ?  peer - > name  :  " (none) " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											it_cdr - > fn_table - > process_dial_end ( it_cdr , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix FRACK message from external redirects; handle outbound channels better
This patch does the following:
 * It simplifies the Dial handling in CDRs. As a rule, the caller in a dial
   relationship is always the Party A. There was some logic present in the
   handling of the dial message that could, conceivably, pick the caller
   as Party A for the beginning of the dial and the peer as Party A for the
   end of the dial. This shouldn't have happened if the code in the bridging
   framework was doing its job; however, that was broken and it led to the
   FRACK. As it is, this code was overly ocmplex and not needed: the caller,
   if present, should always be Party A. Period.
 * It properly checks to see if a channel will continue on in the dialplan.
   ast_check_hangup - much like cake at the end - is a lie. It will tell
   you that you are hungup when you are not. Do not believe it.
   I would make this function tell the truth, but I'm nervous that we've been
   depending on it sitting on its throne of lies for far too long, and it would
   probably break lots of things. So I'm just checking the "internal" soft
   hangup flags, like everyone else.
(closes issue ASTERISK-22060)
Reported by: Mark Michelson
(issue ASTERISK-21831)
Reported by: Matt Jordan
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394290 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-13 23:28:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													caller , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													peer , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													dial_status ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If no CDR handled a dial begin message, make a new one */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( res  & &  ast_strlen_zero ( dial_status ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  cdr_object  * new_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_cdr  =  cdr_object_create_and_append ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! new_cdr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-13 21:27:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_cdr - > fn_table - > process_dial_begin ( new_cdr , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix FRACK message from external redirects; handle outbound channels better
This patch does the following:
 * It simplifies the Dial handling in CDRs. As a rule, the caller in a dial
   relationship is always the Party A. There was some logic present in the
   handling of the dial message that could, conceivably, pick the caller
   as Party A for the beginning of the dial and the peer as Party A for the
   end of the dial. This shouldn't have happened if the code in the bridging
   framework was doing its job; however, that was broken and it led to the
   FRACK. As it is, this code was overly ocmplex and not needed: the caller,
   if present, should always be Party A. Period.
 * It properly checks to see if a channel will continue on in the dialplan.
   ast_check_hangup - much like cake at the end - is a lie. It will tell
   you that you are hungup when you are not. Do not believe it.
   I would make this function tell the truth, but I'm nervous that we've been
   depending on it sitting on its throne of lies for far too long, and it would
   probably break lots of things. So I'm just checking the "internal" soft
   hangup flags, like everyone else.
(closes issue ASTERISK-22060)
Reported by: Mark Michelson
(issue ASTERISK-21831)
Reported by: Matt Jordan
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394290 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-13 23:28:23 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												caller , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												peer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  cdr_object_finalize_party_b ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * party_b  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( it_cdr - > party_b . snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  ! strcasecmp ( it_cdr - > party_b . snapshot - > name ,  party_b - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* Don't transition to the finalized state - let the Party A do
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  that  when  its  ready 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_finalize ( it_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  cdr_object_update_party_b ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * party_b  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! it_cdr - > fn_table - > process_party_b )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( it_cdr - > party_b . snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  ! strcasecmp ( it_cdr - > party_b . snapshot - > name ,  party_b - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											it_cdr - > fn_table - > process_party_b ( it_cdr ,  party_b ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Determine if we need to add a new CDR based on snapshots */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  check_new_cdr_needed ( struct  ast_channel_snapshot  * old_snapshot ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_channel_snapshot  * new_snapshot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If we're dead, we don't need a new CDR */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! new_snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										| |  ( ast_test_flag ( & new_snapshot - > softhangup_flags ,  AST_SOFTHANGUP_HANGUP_EXEC ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_END_BEFORE_H_EXTEN ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Auto-fall through will increment the priority but have no application */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( new_snapshot - > appl ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( old_snapshot  & &  ! snapshot_cep_changed ( old_snapshot ,  new_snapshot ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Handler  for  Stasis - Core  channel  cache  update  messages 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  Passed  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sub  The  stasis  subscription  for  this  message  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  topic  The  topic  this  message  was  published  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  message  The  message 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Multiple revisions 399887,400138,400178,400180-400181
........
  r399887 | dlee | 2013-09-26 10:41:47 -0500 (Thu, 26 Sep 2013) | 1 line
  
  Minor performance bump by not allocate manager variable struct if we don't need it
........
  r400138 | dlee | 2013-09-30 10:24:00 -0500 (Mon, 30 Sep 2013) | 23 lines
  
  Stasis performance improvements
  
  This patch addresses several performance problems that were found in
  the initial performance testing of Asterisk 12.
  
  The Stasis dispatch object was allocated as an AO2 object, even though
  it has a very confined lifecycle. This was replaced with a straight
  ast_malloc().
  
  The Stasis message router was spending an inordinate amount of time
  searching hash tables. In this case, most of our routers had 6 or
  fewer routes in them to begin with. This was replaced with an array
  that's searched linearly for the route.
  
  We more heavily rely on AO2 objects in Asterisk 12, and the memset()
  in ao2_ref() actually became noticeable on the profile. This was
  #ifdef'ed to only run when AO2_DEBUG was enabled.
  
  After being misled by an erroneous comment in taskprocessor.c during
  profiling, the wrong comment was removed.
  
  Review: https://reviewboard.asterisk.org/r/2873/
........
  r400178 | dlee | 2013-09-30 13:26:27 -0500 (Mon, 30 Sep 2013) | 24 lines
  
  Taskprocessor optimization; switch Stasis to use taskprocessors
  
  This patch optimizes taskprocessor to use a semaphore for signaling,
  which the OS can do a better job at managing contention and waiting
  that we can with a mutex and condition.
  
  The taskprocessor execution was also slightly optimized to reduce the
  number of locks taken.
  
  The only observable difference in the taskprocessor implementation is
  that when the final reference to the taskprocessor goes away, it will
  execute all tasks to completion instead of discarding the unexecuted
  tasks.
  
  For systems where unnamed semaphores are not supported, a really
  simple semaphore implementation is provided. (Which gives identical
  performance as the original taskprocessor implementation).
  
  The way we ended up implementing Stasis caused the threadpool to be a
  burden instead of a boost to performance. This was switched to just
  use taskprocessors directly for subscriptions.
  
  Review: https://reviewboard.asterisk.org/r/2881/
........
  r400180 | dlee | 2013-09-30 13:39:34 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Optimize how Stasis forwards are dispatched
  
  This patch optimizes how forwards are dispatched in Stasis.
  
  Originally, forwards were dispatched as subscriptions that are invoked
  on the publishing thread. This did not account for the vast number of
  forwards we would end up having in the system, and the amount of work it
  would take to walk though the forward subscriptions.
  
  This patch modifies Stasis so that rather than walking the tree of
  forwards on every dispatch, when forwards and subscriptions are changed,
  the subscriber list for every topic in the tree is changed.
  
  This has a couple of benefits. First, this reduces the workload of
  dispatching messages. It also reduces contention when dispatching to
  different topics that happen to forward to the same aggregation topic
  (as happens with all of the channel, bridge and endpoint topics).
  
  Since forwards are no longer subscriptions, the bulk of this patch is
  simply changing stasis_subscription objects to stasis_forward objects
  (which, admittedly, I should have done in the first place.)
  
  Since this required me to yet again put in a growing array, I finally
  abstracted that out into a set of ast_vector macros in
  asterisk/vector.h.
  
  Review: https://reviewboard.asterisk.org/r/2883/
........
  r400181 | dlee | 2013-09-30 13:48:57 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Remove dispatch object allocation from Stasis publishing
  
  While looking for areas for performance improvement, I realized that an
  unused feature in Stasis was negatively impacting performance.
  
  When a message is sent to a subscriber, a dispatch object is allocated
  for the dispatch, containing the topic the message was published to, the
  subscriber the message is being sent to, and the message itself.
  
  The topic is actually unused by any subscriber in Asterisk today. And
  the subscriber is associated with the taskprocessor the message is being
  dispatched to.
  
  First, this patch removes the unused topic parameter from Stasis
  subscription callbacks.
  
  Second, this patch introduces the concept of taskprocessor local data,
  data that may be set on a taskprocessor and provided along with the data
  pointer when a task is pushed using the ast_taskprocessor_push_local()
  call. This allows the task to have both data specific to that
  taskprocessor, in addition to data specific to that invocation.
  
  With those two changes, the dispatch object can be removed completely,
  and the message is simply refcounted and sent directly to the
  taskprocessor.
  
  Review: https://reviewboard.asterisk.org/r/2884/
........
Merged revisions 399887,400138,400178,400180-400181 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-30 18:55:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  handle_channel_cache_message ( void  * data ,  struct  stasis_subscription  * sub ,  struct  stasis_message  * message )  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  stasis_cache_update  * update  =  stasis_message_data ( message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * old_snapshot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * new_snapshot ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * uniqueid ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_assert ( update  ! =  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 13:39:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_assert ( ast_channel_snapshot_type ( )  = =  update - > type ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									old_snapshot  =  stasis_message_data ( update - > old_snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									new_snapshot  =  stasis_message_data ( update - > new_snapshot ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uniqueid  =  new_snapshot  ?  new_snapshot - > uniqueid  :  old_snapshot - > uniqueid ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									name  =  new_snapshot  ?  new_snapshot - > name  :  old_snapshot - > name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( filter_channel_cache_message ( old_snapshot ,  new_snapshot ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( new_snapshot  & &  ! old_snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr  =  cdr_object_alloc ( new_snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-18 16:30:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr - > is_root  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_link ( active_cdrs_by_channel ,  cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Handle Party A */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr  =  ao2_find ( active_cdrs_by_channel ,  uniqueid ,  OBJ_KEY ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_WARNING ,  " No CDR for channel %s \n " ,  name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-18 15:28:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( new_snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  all_reject  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ! it_cdr - > fn_table - > process_party_a )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												all_reject  & =  it_cdr - > fn_table - > process_party_a ( it_cdr ,  new_snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( all_reject  & &  check_new_cdr_needed ( old_snapshot ,  new_snapshot ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* We're not hung up and we have a new snapshot - we need a new CDR */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												struct  cdr_object  * new_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												new_cdr  =  cdr_object_create_and_append ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( new_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													new_cdr - > fn_table - > process_party_a ( new_cdr ,  new_snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											CDR_DEBUG ( mod_cfg ,  " %p - Beginning finalize/dispatch for %s \n " ,  cdr ,  old_snapshot - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr_object_finalize ( it_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_dispatch ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_unlink ( active_cdrs_by_channel ,  cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Handle Party B */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( new_snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_callback ( active_cdrs_by_channel ,  OBJ_NODATA ,  cdr_object_update_party_b , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											new_snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_callback ( active_cdrs_by_channel ,  OBJ_NODATA ,  cdr_object_finalize_party_b , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											old_snapshot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  bridge_leave_data  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_snapshot  * bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * channel ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Callback used to notify CDRs of a Party B leaving the bridge */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  cdr_object_party_b_left_bridge_cb ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_leave_data  * leave_data  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2004-06-20 22:46:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( strcmp ( cdr - > bridge ,  leave_data - > bridge - > uniqueid ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( it_cdr - > fn_table  ! =  & bridge_state_fn_table )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! it_cdr - > party_b . snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( strcasecmp ( it_cdr - > party_b . snapshot - > name ,  leave_data - > channel - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* It is our Party B, in our bridge. Set the end time and let the handler
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  transition  our  CDR  appropriately  when  we  leave  the  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_finalize ( it_cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Filter bridge messages based on bridge technology */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  filter_bridge_messages ( struct  ast_bridge_snapshot  * bridge )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Ignore holding bridge technology messages. We treat this simply as an application
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  that  a  channel  enters  into . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! strcmp ( bridge - > technology ,  " holding_bridge " )  & &  strcmp ( bridge - > subclass ,  " parking " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Handler  for  when  a  channel  leaves  a  bridge 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  data  Passed  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sub  The  stasis  subscription  for  this  message  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  topic  The  topic  this  message  was  published  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  message  The  message  -  hopefully  a  bridge  one ! 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  handle_bridge_leave_message ( void  * data ,  struct  stasis_subscription  * sub ,  
						 
					
						
							
								
									
										
											 
										
											
												Multiple revisions 399887,400138,400178,400180-400181
........
  r399887 | dlee | 2013-09-26 10:41:47 -0500 (Thu, 26 Sep 2013) | 1 line
  
  Minor performance bump by not allocate manager variable struct if we don't need it
........
  r400138 | dlee | 2013-09-30 10:24:00 -0500 (Mon, 30 Sep 2013) | 23 lines
  
  Stasis performance improvements
  
  This patch addresses several performance problems that were found in
  the initial performance testing of Asterisk 12.
  
  The Stasis dispatch object was allocated as an AO2 object, even though
  it has a very confined lifecycle. This was replaced with a straight
  ast_malloc().
  
  The Stasis message router was spending an inordinate amount of time
  searching hash tables. In this case, most of our routers had 6 or
  fewer routes in them to begin with. This was replaced with an array
  that's searched linearly for the route.
  
  We more heavily rely on AO2 objects in Asterisk 12, and the memset()
  in ao2_ref() actually became noticeable on the profile. This was
  #ifdef'ed to only run when AO2_DEBUG was enabled.
  
  After being misled by an erroneous comment in taskprocessor.c during
  profiling, the wrong comment was removed.
  
  Review: https://reviewboard.asterisk.org/r/2873/
........
  r400178 | dlee | 2013-09-30 13:26:27 -0500 (Mon, 30 Sep 2013) | 24 lines
  
  Taskprocessor optimization; switch Stasis to use taskprocessors
  
  This patch optimizes taskprocessor to use a semaphore for signaling,
  which the OS can do a better job at managing contention and waiting
  that we can with a mutex and condition.
  
  The taskprocessor execution was also slightly optimized to reduce the
  number of locks taken.
  
  The only observable difference in the taskprocessor implementation is
  that when the final reference to the taskprocessor goes away, it will
  execute all tasks to completion instead of discarding the unexecuted
  tasks.
  
  For systems where unnamed semaphores are not supported, a really
  simple semaphore implementation is provided. (Which gives identical
  performance as the original taskprocessor implementation).
  
  The way we ended up implementing Stasis caused the threadpool to be a
  burden instead of a boost to performance. This was switched to just
  use taskprocessors directly for subscriptions.
  
  Review: https://reviewboard.asterisk.org/r/2881/
........
  r400180 | dlee | 2013-09-30 13:39:34 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Optimize how Stasis forwards are dispatched
  
  This patch optimizes how forwards are dispatched in Stasis.
  
  Originally, forwards were dispatched as subscriptions that are invoked
  on the publishing thread. This did not account for the vast number of
  forwards we would end up having in the system, and the amount of work it
  would take to walk though the forward subscriptions.
  
  This patch modifies Stasis so that rather than walking the tree of
  forwards on every dispatch, when forwards and subscriptions are changed,
  the subscriber list for every topic in the tree is changed.
  
  This has a couple of benefits. First, this reduces the workload of
  dispatching messages. It also reduces contention when dispatching to
  different topics that happen to forward to the same aggregation topic
  (as happens with all of the channel, bridge and endpoint topics).
  
  Since forwards are no longer subscriptions, the bulk of this patch is
  simply changing stasis_subscription objects to stasis_forward objects
  (which, admittedly, I should have done in the first place.)
  
  Since this required me to yet again put in a growing array, I finally
  abstracted that out into a set of ast_vector macros in
  asterisk/vector.h.
  
  Review: https://reviewboard.asterisk.org/r/2883/
........
  r400181 | dlee | 2013-09-30 13:48:57 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Remove dispatch object allocation from Stasis publishing
  
  While looking for areas for performance improvement, I realized that an
  unused feature in Stasis was negatively impacting performance.
  
  When a message is sent to a subscriber, a dispatch object is allocated
  for the dispatch, containing the topic the message was published to, the
  subscriber the message is being sent to, and the message itself.
  
  The topic is actually unused by any subscriber in Asterisk today. And
  the subscriber is associated with the taskprocessor the message is being
  dispatched to.
  
  First, this patch removes the unused topic parameter from Stasis
  subscription callbacks.
  
  Second, this patch introduces the concept of taskprocessor local data,
  data that may be set on a taskprocessor and provided along with the data
  pointer when a task is pushed using the ast_taskprocessor_push_local()
  call. This allows the task to have both data specific to that
  taskprocessor, in addition to data specific to that invocation.
  
  With those two changes, the dispatch object can be removed completely,
  and the message is simply refcounted and sent directly to the
  taskprocessor.
  
  Review: https://reviewboard.asterisk.org/r/2884/
........
Merged revisions 399887,400138,400178,400180-400181 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-30 18:55:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  stasis_message  * message ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_blob  * update  =  stasis_message_data ( message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_snapshot  * bridge  =  update - > bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * channel  =  update - > channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_find ( active_cdrs_by_channel ,  channel - > uniqueid ,  OBJ_KEY ) , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  bridge_leave_data  leave_data  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. bridge  =  bridge , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										. channel  =  channel , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  left_bridge  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( filter_bridge_messages ( bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-01 15:54:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( filter_channel_snapshot ( channel ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									CDR_DEBUG ( mod_cfg ,  " Bridge Leave message for %s: %u.%08u \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											channel - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( unsigned  int ) stasis_message_timestamp ( message ) - > tv_sec , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( unsigned  int ) stasis_message_timestamp ( message ) - > tv_usec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_WARNING ,  " No CDR for channel %s \n " ,  channel - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-18 15:28:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Party A */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! it_cdr - > fn_table - > process_bridge_leave )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										CDR_DEBUG ( mod_cfg ,  " %p - Processing Bridge Leave for %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												it_cdr ,  channel - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! it_cdr - > fn_table - > process_bridge_leave ( it_cdr ,  bridge ,  channel ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_string_field_set ( it_cdr ,  bridge ,  " " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											left_bridge  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-13 21:27:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! left_bridge )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( strcmp ( bridge - > subclass ,  " parking " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Party B */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_callback ( active_cdrs_by_channel ,  OBJ_NODATA , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												cdr_object_party_b_left_bridge_cb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												& leave_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
									
										
										
										
											2013-08-16 17:33:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Create  a  new  CDR ,  append  it  to  an  existing  CDR ,  and  update  its  snapshots 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ note  The  new  CDR  will  be  automatically  transitioned  to  the  bridge  state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  bridge_candidate_add_to_cdr ( struct  cdr_object  * cdr ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  cdr_object_snapshot  * party_b ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,   mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * new_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									new_cdr  =  cdr_object_create_and_append ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! new_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr_object_snapshot_copy ( & new_cdr - > party_b ,  party_b ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_check_party_a_answer ( new_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_string_field_set ( new_cdr ,  bridge ,  cdr - > bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_object_transition_state ( new_cdr ,  & bridge_state_fn_table ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									CDR_DEBUG ( mod_cfg ,  " %p - Party A %s has new Party B %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_cdr ,  new_cdr - > party_a . snapshot - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										party_b - > snapshot - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Process  a  single  \ ref  bridge_candidate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  When  a  CDR  enters  a  bridge ,  it  needs  to  make  pairings  with  everyone  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  that  it  is  not  currently  paired  with .  This  function  determines ,  for  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  CDR  for  the  channel  that  entered  the  bridge  and  the  CDR  for  every  other 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  channel  currently  in  the  bridge ,  who  is  Party  A  and  makes  new  CDRs . 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ param  cdr  The  \ ref  cdr_obj  being  processed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cand_cdr  The  \ ref  cdr_object  that  is  a  candidate 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  bridge_candidate_process ( struct  cdr_object  * cdr ,  struct  cdr_object  * base_cand_cdr )  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object_snapshot  * party_a ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * cand_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									SCOPED_AO2LOCK ( lock ,  base_cand_cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( cand_cdr  =  base_cand_cdr ;  cand_cdr ;  cand_cdr  =  cand_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Skip any records that are not in this bridge */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( strcmp ( cand_cdr - > bridge ,  cdr - > bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If the candidate is us or someone we've taken on, pass on by */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( cdr - > party_a . snapshot - > name ,  cand_cdr - > party_a . snapshot - > name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											| |  ( cdr - > party_b . snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												& &  ! strcasecmp ( cdr - > party_b . snapshot - > name ,  cand_cdr - > party_a . snapshot - > name ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										party_a  =  cdr_object_pick_party_a ( & cdr - > party_a ,  & cand_cdr - > party_a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We're party A - make a new CDR, append it to us, and set the candidate as
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Party  B  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( party_a - > snapshot - > name ,  cdr - > party_a . snapshot - > name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge_candidate_add_to_cdr ( cdr ,  & cand_cdr - > party_a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We're Party B. Check if we can add ourselves immediately or if we need
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  a  new  CDR  for  them  ( they  already  have  a  Party  B )  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cand_cdr - > party_b . snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& &  strcasecmp ( cand_cdr - > party_b . snapshot - > name ,  cdr - > party_a . snapshot - > name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bridge_candidate_add_to_cdr ( cand_cdr ,  & cdr - > party_a ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											CDR_DEBUG ( mod_cfg ,  " %p - Party A %s has new Party B %s \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cand_cdr ,  cand_cdr - > party_a . snapshot - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr - > party_a . snapshot - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_snapshot_copy ( & cand_cdr - > party_b ,  & cdr - > party_a ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* It's possible that this joined at one point and was never chosen
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  as  party  A .  Clear  their  end  time ,  as  it  would  be  set  in  such  a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  case . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											memset ( & cand_cdr - > end ,  0 ,  sizeof ( cand_cdr - > end ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												main/cdr: Fix crash/memory consumption in CDRs in multi-party bridge scenarios
This patch fixes an issue where CDRs would get stuck generating an infinite
number of CDRs, eventually crashing Asterisk (and consuming a lot of memory
along the way).
When a channel enters into a multi-party bridge, the CDR engine creates
mappings of each participant to each other participant, picking the 'A' party
as it goes. So, if we have four channels in a multi-party bridge (Alice, Bob,
Charlie, Denise), we would have something like:
Alice => Bob
Alice => Charlie
Alice => Denise
Bob => Charlie
Bob => Denise
Charlie => Denise
This works fine when participants enter the bridge a single time.
When a participant leaves a bridge, the CDRs for that channel are transitioned
to a finalized state.
The bug occurs if Bob rejoins. When the CDR engine creates mappings between the
channels, it walks through all the participants currently in the bridge, and
realizes that no one in the bridge can create a CDR with the channel (Bob).
As such it creates a new CDR for the candidate and appends it to that
candidate's chain. Unfortunately, on this particular code path, it doesn't
stop traversing the candidate's chain. Since we just added ourselves to the
chain, this causes the loop to keep going, constantly adding new CDRs.
This patch makes it so the engine bails when it creates a CDR match in this
case.
Review: https://reviewboard.asterisk.org/r/3964/
ASTERISK-24241 #close
Reported by: Deepak Singh Rawat
Tested by: Deepak Singh Rawat
ASTERISK-24208
Reported by: Frankie Chin
........
Merged revisions 422715 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 422716 from http://svn.asterisk.org/svn/asterisk/branches/13
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@422717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-09-05 21:56:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Handle  creating  bridge  pairings  for  the  \ ref  cdr_object  that  just 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  entered  a  bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr  The  \ ref  cdr_object  that  just  entered  the  bridge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  The  \ ref  ast_bridge_snapshot  representing  the  bridge  it  just  entered 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  handle_bridge_pairings ( struct  cdr_object  * cdr ,  struct  ast_bridge_snapshot  * bridge )  
						 
					
						
							
								
									
										
										
										
											2007-02-14 20:22:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ao2_iterator  it_channels ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * channel_id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									it_channels  =  ao2_iterator_init ( bridge - > channels ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( channel_id  =  ao2_iterator_next ( & it_channels ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RAII_VAR ( struct  cdr_object  * ,  cand_cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_find ( active_cdrs_by_channel ,  channel_id ,  OBJ_KEY ) , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! cand_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( channel_id ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bridge_candidate_process ( cdr ,  cand_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( channel_id ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & it_channels ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-02-14 20:22:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Handle entering into a parking bridge
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr  The  CDR  to  operate  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  The  bridge  the  channel  just  entered 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  channel  The  channel  snapshot 
							 
						 
					
						
							
								
									
										
										
										
											2011-06-01 23:12:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  handle_parking_bridge_enter_message ( struct  cdr_object  * cdr ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_snapshot  * bridge , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_channel_snapshot  * channel ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * new_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( it_cdr - > fn_table - > process_parking_bridge_enter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											res  & =  it_cdr - > fn_table - > process_parking_bridge_enter ( it_cdr ,  bridge ,  channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( it_cdr - > fn_table - > process_party_a )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											CDR_DEBUG ( mod_cfg ,  " %p - Updating Party A %s snapshot \n " ,  it_cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													channel - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											it_cdr - > fn_table - > process_party_a ( it_cdr ,  channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* No one handled it - we need a new one! */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_cdr  =  cdr_object_create_and_append ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( new_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Let the single state transition us to Parked */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_transition_state ( new_cdr ,  & single_state_fn_table ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											new_cdr - > fn_table - > process_parking_bridge_enter ( new_cdr ,  bridge ,  channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*! \brief Handle a bridge enter message for a 'normal' bridge
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  cdr  The  CDR  to  operate  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  bridge  The  bridge  the  channel  just  entered 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  channel  The  channel  snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  handle_standard_bridge_enter_message ( struct  cdr_object  * cdr ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_bridge_snapshot  * bridge , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_channel_snapshot  * channel ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									enum  process_bridge_enter_results  result ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * new_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * handled_cdr  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( it_cdr - > fn_table - > process_party_a )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											CDR_DEBUG ( mod_cfg ,  " %p - Updating Party A %s snapshot \n " ,  it_cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													channel - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											it_cdr - > fn_table - > process_party_a ( it_cdr ,  channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Notify all states that they have entered a bridge */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( it_cdr - > fn_table - > process_bridge_enter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											CDR_DEBUG ( mod_cfg ,  " %p - Processing bridge enter for %s \n " ,  it_cdr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													channel - > name ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											result  =  it_cdr - > fn_table - > process_bridge_enter ( it_cdr ,  bridge ,  channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											switch  ( result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  BRIDGE_ENTER_ONLY_PARTY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* Fall through */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											case  BRIDGE_ENTER_OBTAINED_PARTY_B : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ! handled_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													handled_cdr  =  it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-13 21:27:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											case  BRIDGE_ENTER_NEED_CDR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* Pass */ 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-13 21:27:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											case  BRIDGE_ENTER_NO_PARTY_B : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* We didn't win on any - end this CDR. If someone else comes in later
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  that  is  Party  B  to  this  CDR ,  it  can  re - activate  this  CDR . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ! handled_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													handled_cdr  =  it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr_object_finalize ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-13 21:27:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Create the new matchings, but only for either:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *   *  The  first  CDR  in  the  chain  that  handled  it .  This  avoids  issues  with 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *     forked  CDRs . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *   *  If  no  one  handled  it ,  the  last  CDR  in  the  chain .  This  would  occur  if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *     a  CDR  joined  a  bridge  and  it  wasn ' t  Party  A  for  anyone .  We  still  need 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *     to  make  pairings  with  everyone  in  the  bridge . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( handled_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										handle_bridge_pairings ( handled_cdr ,  bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Nothing handled it - we need a new one! */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_cdr  =  cdr_object_create_and_append ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( new_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* This is guaranteed to succeed: the new CDR is created in the single state
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  and  will  be  able  to  handle  the  bridge  enter  message 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											handle_standard_bridge_enter_message ( cdr ,  bridge ,  channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Handler  for  Stasis - Core  bridge  enter  messages 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  Passed  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sub  The  stasis  subscription  for  this  message  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  topic  The  topic  this  message  was  published  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  message  The  message  -  hopefully  a  bridge  one ! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  handle_bridge_enter_message ( void  * data ,  struct  stasis_subscription  * sub ,  
						 
					
						
							
								
									
										
											 
										
											
												Multiple revisions 399887,400138,400178,400180-400181
........
  r399887 | dlee | 2013-09-26 10:41:47 -0500 (Thu, 26 Sep 2013) | 1 line
  
  Minor performance bump by not allocate manager variable struct if we don't need it
........
  r400138 | dlee | 2013-09-30 10:24:00 -0500 (Mon, 30 Sep 2013) | 23 lines
  
  Stasis performance improvements
  
  This patch addresses several performance problems that were found in
  the initial performance testing of Asterisk 12.
  
  The Stasis dispatch object was allocated as an AO2 object, even though
  it has a very confined lifecycle. This was replaced with a straight
  ast_malloc().
  
  The Stasis message router was spending an inordinate amount of time
  searching hash tables. In this case, most of our routers had 6 or
  fewer routes in them to begin with. This was replaced with an array
  that's searched linearly for the route.
  
  We more heavily rely on AO2 objects in Asterisk 12, and the memset()
  in ao2_ref() actually became noticeable on the profile. This was
  #ifdef'ed to only run when AO2_DEBUG was enabled.
  
  After being misled by an erroneous comment in taskprocessor.c during
  profiling, the wrong comment was removed.
  
  Review: https://reviewboard.asterisk.org/r/2873/
........
  r400178 | dlee | 2013-09-30 13:26:27 -0500 (Mon, 30 Sep 2013) | 24 lines
  
  Taskprocessor optimization; switch Stasis to use taskprocessors
  
  This patch optimizes taskprocessor to use a semaphore for signaling,
  which the OS can do a better job at managing contention and waiting
  that we can with a mutex and condition.
  
  The taskprocessor execution was also slightly optimized to reduce the
  number of locks taken.
  
  The only observable difference in the taskprocessor implementation is
  that when the final reference to the taskprocessor goes away, it will
  execute all tasks to completion instead of discarding the unexecuted
  tasks.
  
  For systems where unnamed semaphores are not supported, a really
  simple semaphore implementation is provided. (Which gives identical
  performance as the original taskprocessor implementation).
  
  The way we ended up implementing Stasis caused the threadpool to be a
  burden instead of a boost to performance. This was switched to just
  use taskprocessors directly for subscriptions.
  
  Review: https://reviewboard.asterisk.org/r/2881/
........
  r400180 | dlee | 2013-09-30 13:39:34 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Optimize how Stasis forwards are dispatched
  
  This patch optimizes how forwards are dispatched in Stasis.
  
  Originally, forwards were dispatched as subscriptions that are invoked
  on the publishing thread. This did not account for the vast number of
  forwards we would end up having in the system, and the amount of work it
  would take to walk though the forward subscriptions.
  
  This patch modifies Stasis so that rather than walking the tree of
  forwards on every dispatch, when forwards and subscriptions are changed,
  the subscriber list for every topic in the tree is changed.
  
  This has a couple of benefits. First, this reduces the workload of
  dispatching messages. It also reduces contention when dispatching to
  different topics that happen to forward to the same aggregation topic
  (as happens with all of the channel, bridge and endpoint topics).
  
  Since forwards are no longer subscriptions, the bulk of this patch is
  simply changing stasis_subscription objects to stasis_forward objects
  (which, admittedly, I should have done in the first place.)
  
  Since this required me to yet again put in a growing array, I finally
  abstracted that out into a set of ast_vector macros in
  asterisk/vector.h.
  
  Review: https://reviewboard.asterisk.org/r/2883/
........
  r400181 | dlee | 2013-09-30 13:48:57 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Remove dispatch object allocation from Stasis publishing
  
  While looking for areas for performance improvement, I realized that an
  unused feature in Stasis was negatively impacting performance.
  
  When a message is sent to a subscriber, a dispatch object is allocated
  for the dispatch, containing the topic the message was published to, the
  subscriber the message is being sent to, and the message itself.
  
  The topic is actually unused by any subscriber in Asterisk today. And
  the subscriber is associated with the taskprocessor the message is being
  dispatched to.
  
  First, this patch removes the unused topic parameter from Stasis
  subscription callbacks.
  
  Second, this patch introduces the concept of taskprocessor local data,
  data that may be set on a taskprocessor and provided along with the data
  pointer when a task is pushed using the ast_taskprocessor_push_local()
  call. This allows the task to have both data specific to that
  taskprocessor, in addition to data specific to that invocation.
  
  With those two changes, the dispatch object can be removed completely,
  and the message is simply refcounted and sent directly to the
  taskprocessor.
  
  Review: https://reviewboard.asterisk.org/r/2884/
........
Merged revisions 399887,400138,400178,400180-400181 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-30 18:55:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  stasis_message  * message ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_blob  * update  =  stasis_message_data ( message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_bridge_snapshot  * bridge  =  update - > bridge ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * channel  =  update - > channel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_find ( active_cdrs_by_channel ,  channel - > uniqueid ,  OBJ_KEY ) , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( filter_bridge_messages ( bridge ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-16 02:37:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( filter_channel_snapshot ( channel ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									CDR_DEBUG ( mod_cfg ,  " Bridge Enter message for channel %s: %u.%08u \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											channel - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( unsigned  int ) stasis_message_timestamp ( message ) - > tv_sec , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( unsigned  int ) stasis_message_timestamp ( message ) - > tv_usec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_WARNING ,  " No CDR for channel %s \n " ,  channel - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-18 15:28:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! strcmp ( bridge - > subclass ,  " parking " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										handle_parking_bridge_enter_message ( cdr ,  bridge ,  channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										handle_standard_bridge_enter_message ( cdr ,  bridge ,  channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Handler  for  when  a  channel  is  parked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  Passed  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sub  The  stasis  subscription  for  this  message  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  topic  The  topic  this  message  was  published  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  message  The  message  about  who  got  parked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  handle_parked_call_message ( void  * data ,  struct  stasis_subscription  * sub ,  
						 
					
						
							
								
									
										
											 
										
											
												Multiple revisions 399887,400138,400178,400180-400181
........
  r399887 | dlee | 2013-09-26 10:41:47 -0500 (Thu, 26 Sep 2013) | 1 line
  
  Minor performance bump by not allocate manager variable struct if we don't need it
........
  r400138 | dlee | 2013-09-30 10:24:00 -0500 (Mon, 30 Sep 2013) | 23 lines
  
  Stasis performance improvements
  
  This patch addresses several performance problems that were found in
  the initial performance testing of Asterisk 12.
  
  The Stasis dispatch object was allocated as an AO2 object, even though
  it has a very confined lifecycle. This was replaced with a straight
  ast_malloc().
  
  The Stasis message router was spending an inordinate amount of time
  searching hash tables. In this case, most of our routers had 6 or
  fewer routes in them to begin with. This was replaced with an array
  that's searched linearly for the route.
  
  We more heavily rely on AO2 objects in Asterisk 12, and the memset()
  in ao2_ref() actually became noticeable on the profile. This was
  #ifdef'ed to only run when AO2_DEBUG was enabled.
  
  After being misled by an erroneous comment in taskprocessor.c during
  profiling, the wrong comment was removed.
  
  Review: https://reviewboard.asterisk.org/r/2873/
........
  r400178 | dlee | 2013-09-30 13:26:27 -0500 (Mon, 30 Sep 2013) | 24 lines
  
  Taskprocessor optimization; switch Stasis to use taskprocessors
  
  This patch optimizes taskprocessor to use a semaphore for signaling,
  which the OS can do a better job at managing contention and waiting
  that we can with a mutex and condition.
  
  The taskprocessor execution was also slightly optimized to reduce the
  number of locks taken.
  
  The only observable difference in the taskprocessor implementation is
  that when the final reference to the taskprocessor goes away, it will
  execute all tasks to completion instead of discarding the unexecuted
  tasks.
  
  For systems where unnamed semaphores are not supported, a really
  simple semaphore implementation is provided. (Which gives identical
  performance as the original taskprocessor implementation).
  
  The way we ended up implementing Stasis caused the threadpool to be a
  burden instead of a boost to performance. This was switched to just
  use taskprocessors directly for subscriptions.
  
  Review: https://reviewboard.asterisk.org/r/2881/
........
  r400180 | dlee | 2013-09-30 13:39:34 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Optimize how Stasis forwards are dispatched
  
  This patch optimizes how forwards are dispatched in Stasis.
  
  Originally, forwards were dispatched as subscriptions that are invoked
  on the publishing thread. This did not account for the vast number of
  forwards we would end up having in the system, and the amount of work it
  would take to walk though the forward subscriptions.
  
  This patch modifies Stasis so that rather than walking the tree of
  forwards on every dispatch, when forwards and subscriptions are changed,
  the subscriber list for every topic in the tree is changed.
  
  This has a couple of benefits. First, this reduces the workload of
  dispatching messages. It also reduces contention when dispatching to
  different topics that happen to forward to the same aggregation topic
  (as happens with all of the channel, bridge and endpoint topics).
  
  Since forwards are no longer subscriptions, the bulk of this patch is
  simply changing stasis_subscription objects to stasis_forward objects
  (which, admittedly, I should have done in the first place.)
  
  Since this required me to yet again put in a growing array, I finally
  abstracted that out into a set of ast_vector macros in
  asterisk/vector.h.
  
  Review: https://reviewboard.asterisk.org/r/2883/
........
  r400181 | dlee | 2013-09-30 13:48:57 -0500 (Mon, 30 Sep 2013) | 28 lines
  
  Remove dispatch object allocation from Stasis publishing
  
  While looking for areas for performance improvement, I realized that an
  unused feature in Stasis was negatively impacting performance.
  
  When a message is sent to a subscriber, a dispatch object is allocated
  for the dispatch, containing the topic the message was published to, the
  subscriber the message is being sent to, and the message itself.
  
  The topic is actually unused by any subscriber in Asterisk today. And
  the subscriber is associated with the taskprocessor the message is being
  dispatched to.
  
  First, this patch removes the unused topic parameter from Stasis
  subscription callbacks.
  
  Second, this patch introduces the concept of taskprocessor local data,
  data that may be set on a taskprocessor and provided along with the data
  pointer when a task is pushed using the ast_taskprocessor_push_local()
  call. This allows the task to have both data specific to that
  taskprocessor, in addition to data specific to that invocation.
  
  With those two changes, the dispatch object can be removed completely,
  and the message is simply refcounted and sent directly to the
  taskprocessor.
  
  Review: https://reviewboard.asterisk.org/r/2884/
........
Merged revisions 399887,400138,400178,400180-400181 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-30 18:55:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  stasis_message  * message ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_parked_call_payload  * payload  =  stasis_message_data ( message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * channel  =  payload - > parkee ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-28 20:55:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  unhandled  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Anything other than getting parked will be handled by other updates */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( payload - > event_type  ! =  PARKED_CALL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* No one got parked? */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! channel )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-01 15:54:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( filter_channel_snapshot ( channel ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									CDR_DEBUG ( mod_cfg ,  " Parked Call message for channel %s: %u.%08u \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											channel - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( unsigned  int ) stasis_message_timestamp ( message ) - > tv_sec , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( unsigned  int ) stasis_message_timestamp ( message ) - > tv_usec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr  =  ao2_find ( active_cdrs_by_channel ,  channel - > uniqueid ,  OBJ_KEY ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_WARNING ,  " No CDR for channel %s \n " ,  channel - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-18 15:28:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( it_cdr - > fn_table - > process_parked_channel )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-28 20:55:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											unhandled  & =  it_cdr - > fn_table - > process_parked_channel ( it_cdr ,  payload ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( unhandled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Nothing handled the messgae - we need a new one! */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  cdr_object  * new_cdr  =  cdr_object_create_and_append ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( new_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* As the new CDR is created in the single state, it is guaranteed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  to  have  a  function  for  the  parked  call  message  and  will  handle 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  the  message  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											new_cdr - > fn_table - > process_parked_channel ( new_cdr ,  payload ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-28 15:50:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Handler  for  a  synchronization  message 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  data  Passed  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  sub  The  stasis  subscription  for  this  message  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  topic  The  topic  this  message  was  published  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  message  A  blank  ao2  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  handle_cdr_sync_message ( void  * data ,  struct  stasis_subscription  * sub ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  stasis_message  * message ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_cdr_config  * ast_cdr_get_config ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( mod_cfg - > general ,  + 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  mod_cfg - > general ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_cdr_set_config ( struct  ast_cdr_config  * config )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_cleanup ( mod_cfg - > general ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mod_cfg - > general  =  config ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_ref ( mod_cfg - > general ,  + 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_toggle_runtime_options ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_cdr_is_enabled ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_ENABLED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_backend_suspend ( const  char  * name )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  success  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_beitem  * i  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_WRLOCK ( & be_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( & be_list ,  i ,  list )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( name ,  i - > name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 3 ,  " Suspending CDR backend %s \n " ,  i - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											i - > suspended  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											success  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & be_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  success ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_cdr_backend_unsuspend ( const  char  * name )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  success  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_beitem  * i  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_WRLOCK ( & be_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( & be_list ,  i ,  list )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( name ,  i - > name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_debug ( 3 ,  " Unsuspending CDR backend %s \n " ,  i - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											i - > suspended  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											success  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( & be_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  success ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  cdr_generic_register ( struct  be_list  * generic_list ,  const  char  * name ,  const  char  * desc ,  ast_cdrbe  be )  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_beitem  * i  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ! name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-18 16:37:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ! be )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_WARNING ,  " CDR engine '%s' lacks backend \n " ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_RWLIST_WRLOCK ( generic_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( generic_list ,  i ,  list )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-18 16:37:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( name ,  i - > name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " Already have a CDR backend called '%s' \n " ,  name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											AST_RWLIST_UNLOCK ( generic_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-18 16:37:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ( i  =  ast_calloc ( 1 ,  sizeof ( * i ) ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									i - > be  =  be ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_copy_string ( i - > name ,  name ,  sizeof ( i - > name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_copy_string ( i - > desc ,  desc ,  sizeof ( i - > desc ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_RWLIST_INSERT_HEAD ( generic_list ,  i ,  list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( generic_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_register ( const  char  * name ,  const  char  * desc ,  ast_cdrbe  be )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cdr_generic_register ( & be_list ,  name ,  desc ,  be ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_cdr_modifier_register ( const  char  * name ,  const  char  * desc ,  ast_cdrbe  be )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  cdr_generic_register ( ( struct  be_list  * ) & mo_list ,  name ,  desc ,  be ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  ast_cdr_generic_unregister ( struct  be_list  * generic_list ,  const  char  * name )  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_beitem  * match  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  active_count ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_RWLIST_WRLOCK ( generic_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_TRAVERSE ( generic_list ,  match ,  list )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( name ,  match - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-03 21:21:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! match )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_RWLIST_UNLOCK ( generic_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									active_count  =  ao2_container_count ( active_cdrs_by_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! match - > suspended  & &  active_count  ! =  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_RWLIST_UNLOCK ( generic_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_log ( AST_LOG_WARNING ,  " Unable to unregister CDR backend %s; %d CDRs are still active \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											name ,  active_count ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_RWLIST_REMOVE ( generic_list ,  match ,  list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_RWLIST_UNLOCK ( generic_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_verb ( 2 ,  " Unregistered '%s' CDR backend \n " ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_free ( match ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-03 21:21:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_unregister ( const  char  * name )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ast_cdr_generic_unregister ( & be_list ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_cdr_modifier_unregister ( const  char  * name )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ast_cdr_generic_unregister ( ( struct  be_list  * ) & mo_list ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_cdr  * ast_cdr_dup ( struct  ast_cdr  * cdr )  
						 
					
						
							
								
									
										
										
										
											2005-06-17 00:37:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2007-03-30 17:57:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_cdr  * newcdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-30 17:57:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-30 17:57:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									newcdr  =  ast_cdr_alloc ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! newcdr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-17 12:51:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-17 00:37:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:24:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* newcdr  =  * cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_LIST_HEAD_INIT_NOLOCK ( & newcdr - > varshead ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									copy_variables ( & newcdr - > varshead ,  & cdr - > varshead ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-10-27 21:57:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									newcdr - > next  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-17 12:51:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-06-17 00:37:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  newcdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  const  char  * cdr_format_var_internal ( struct  ast_cdr  * cdr ,  const  char  * name )  
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_var_t  * variables ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:24:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & cdr - > varshead ,  variables ,  entries )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( name ,  ast_var_name ( variables ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ast_var_value ( variables ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:24:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-08-10 19:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  cdr_get_tv ( struct  timeval  when ,  const  char  * fmt ,  char  * buf ,  int  bufsize )  
						 
					
						
							
								
									
										
										
										
											2006-04-06 16:01:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( fmt  = =  NULL )  { 	/* raw mode */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-08-10 19:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										snprintf ( buf ,  bufsize ,  " %ld.%06ld " ,  ( long ) when . tv_sec ,  ( long ) when . tv_usec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-03-10 14:55:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 23:15:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										buf [ 0 ]  =  ' \0 ' ; /* Ensure the buffer is initialized. */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-08-10 19:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( when . tv_sec )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-03-10 14:55:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											struct  ast_tm  tm ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-08-10 19:35:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_localtime ( & when ,  & tm ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-03-10 14:55:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_strftime ( buf ,  bufsize ,  fmt ,  & tm ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-06 16:01:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_cdr_format_var ( struct  ast_cdr  * cdr ,  const  char  * name ,  char  * * ret ,  char  * workspace ,  int  workspacelen ,  int  raw )  
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * fmt  =  " %Y-%m-%d %T " ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * varbuf ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-30 17:57:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-30 17:57:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* ret  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! strcasecmp ( name ,  " clid " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > clid ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " src " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > src ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " dst " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > dst ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " dcontext " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > dcontext ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " channel " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > channel ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " dstchannel " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > dstchannel ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " lastapp " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > lastapp ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " lastdata " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > lastdata ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " start " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-06 16:01:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_get_tv ( cdr - > start ,  raw  ?  NULL  :  fmt ,  workspace ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " answer " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-06 16:01:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_get_tv ( cdr - > answer ,  raw  ?  NULL  :  fmt ,  workspace ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " end " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-06 16:01:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_get_tv ( cdr - > end ,  raw  ?  NULL  :  fmt ,  workspace ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " duration " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2012-06-25 19:39:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										snprintf ( workspace ,  workspacelen ,  " %ld " ,  cdr - > end . tv_sec  ! =  0  ?  cdr - > duration  :  ( long ) ast_tvdiff_ms ( ast_tvnow ( ) ,  cdr - > start )  /  1000 ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix incorrect billing duration reported when batch mode is enabled
Similar to r369351, the billing duration can be skewed when batch mode is
enabled.  This happened much more rarely than the duration, as it only
occured when the call was answered (thereby indicating an actual answer
time) and immediately hung up on (indicating a billsec of 0).  Since
a billing time of '0' can either mean that the call immediately ended
or that the CDR was improperly answered, we have to use additional information
to know whether or not we can trust the CDR billsec value.  Prior to this
patch, we looked to see if we had a valid answer time.  If we did, and
billsec was zero, we used the current time to calculate what billsec value
we could from the CDR being written.  If batch mode is enabled, this will
incorrectly report a billsec value being much greater than the actual
duration of the call.
Instead of relying on the presence of an answer time to know whether or not
we can re-calculate the billsec for the CDR, we now also use the presence
of the CDR's end time to know if we need to re-calculate or whether we can
trust the billsec value that we have.  This prevents erroneous jumps in the
billsec value, while still making sure that in the worst case, some billing
time will be calculated.
(closes issue AST-1016)
Reported by: Thomas Arimont
Tested by: Thomas Arimont
........
Merged revisions 374843 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 374844 from http://svn.asterisk.org/svn/asterisk/branches/10
........
Merged revisions 374845 from http://svn.asterisk.org/svn/asterisk/branches/11
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@374846 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2012-10-11 15:44:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " billsec " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										snprintf ( workspace ,  workspacelen ,  " %ld " ,  ( cdr - > billsec  | |  ! ast_tvzero ( cdr - > end )  | |  ast_tvzero ( cdr - > answer ) )  ?  cdr - > billsec  :  ( long ) ast_tvdiff_ms ( ast_tvnow ( ) ,  cdr - > answer )  /  1000 ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix incorrect billing duration reported when batch mode is enabled
Similar to r369351, the billing duration can be skewed when batch mode is
enabled.  This happened much more rarely than the duration, as it only
occured when the call was answered (thereby indicating an actual answer
time) and immediately hung up on (indicating a billsec of 0).  Since
a billing time of '0' can either mean that the call immediately ended
or that the CDR was improperly answered, we have to use additional information
to know whether or not we can trust the CDR billsec value.  Prior to this
patch, we looked to see if we had a valid answer time.  If we did, and
billsec was zero, we used the current time to calculate what billsec value
we could from the CDR being written.  If batch mode is enabled, this will
incorrectly report a billsec value being much greater than the actual
duration of the call.
Instead of relying on the presence of an answer time to know whether or not
we can re-calculate the billsec for the CDR, we now also use the presence
of the CDR's end time to know if we need to re-calculate or whether we can
trust the billsec value that we have.  This prevents erroneous jumps in the
billsec value, while still making sure that in the worst case, some billing
time will be calculated.
(closes issue AST-1016)
Reported by: Thomas Arimont
Tested by: Thomas Arimont
........
Merged revisions 374843 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 374844 from http://svn.asterisk.org/svn/asterisk/branches/10
........
Merged revisions 374845 from http://svn.asterisk.org/svn/asterisk/branches/11
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@374846 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2012-10-11 15:44:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " disposition " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-23 23:12:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( raw )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-03-01 17:53:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											snprintf ( workspace ,  workspacelen ,  " %ld " ,  cdr - > disposition ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-23 23:12:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_copy_string ( workspace ,  ast_cdr_disp2str ( cdr - > disposition ) ,  workspacelen ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " amaflags " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( raw )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-03-01 17:53:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											snprintf ( workspace ,  workspacelen ,  " %ld " ,  cdr - > amaflags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-23 23:12:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_copy_string ( workspace ,  ast_channel_amaflags2string ( cdr - > amaflags ) ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-23 23:12:41 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " accountcode " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > accountcode ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " peeraccount " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-26 15:28:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > peeraccount ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " uniqueid " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > uniqueid ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " linkedid " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-26 15:28:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > linkedid ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " userfield " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  cdr - > userfield ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " sequence " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-03 21:21:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										snprintf ( workspace ,  workspacelen ,  " %d " ,  cdr - > sequence ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ( varbuf  =  cdr_format_var_internal ( cdr ,  name ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_copy_string ( workspace ,  varbuf ,  workspacelen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-08-14 18:07:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										workspace [ 0 ]  =  ' \0 ' ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_strlen_zero ( workspace ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										* ret  =  workspace ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Callback  that  finds  all  CDRs  that  reference  a  particular  channel  by  name 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  cdr_object_select_all_by_name_cb ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * name  =  arg ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! strcasecmp ( cdr - > party_a . snapshot - > name ,  name )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( cdr - > party_b . snapshot  & &  ! strcasecmp ( cdr - > party_b . snapshot - > name ,  name ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CMP_MATCH ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Callback  that  finds  a  CDR  by  channel  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  cdr_object_get_by_name_cb ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * name  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! strcasecmp ( cdr - > party_a . snapshot - > name ,  name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CMP_MATCH ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* Read Only CDR variables */  
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:56:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  const  char  *  const  cdr_readonly_vars [ ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" clid " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" src " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" dst " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" dcontext " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" channel " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" dstchannel " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" lastapp " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" lastdata " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" start " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" answer " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" end " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" duration " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" billsec " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" disposition " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" amaflags " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" accountcode " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" uniqueid " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" linkedid " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" userfield " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									" sequence " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									NULL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_cdr_setvar ( const  char  * channel_name ,  const  char  * name ,  const  char  * value )  
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_iterator  * it_cdrs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * arg  =  ast_strdupa ( channel_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-05 15:07:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  x ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-01-23 00:11:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( x  =  0 ;  cdr_readonly_vars [ x ] ;  x + + )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-29 05:45:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( name ,  cdr_readonly_vars [ x ] ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Attempt to set the '%s' read-only variable! \n " ,  name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-05 15:07:49 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									it_cdrs  =  ao2_callback ( active_cdrs_by_channel ,  OBJ_MULTIPLE ,  cdr_object_select_all_by_name_cb ,  arg ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! it_cdrs )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_ERROR ,  " Unable to find CDR for channel %s \n " ,  channel_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-06 12:45:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( ;  ( cdr  =  ao2_iterator_next ( it_cdrs ) ) ;  ao2_unlock ( cdr ) ,  ao2_cleanup ( cdr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  varshead  * headp  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:24:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												main/cdr: Allow setting properties on a finalized CDR if it is the last one
Prior to this patch, we explicitly disallowed setting any properties on a
finalized CDR. This seemed like a good idea at the time; in practice, it was
more restrictive.
There are weird and strange scenarios where setting a property on a finalized
CDR is definitely wrong. For example, we may Fork a CDR, finalizing the
previous one, then change a property. In said case, the old CDR is supposed
to now be 'immutable' (so to speak), and should not be updated. From the
perspective of the code, a forked CDR that is finalized is just finalized.
Hence why we decided these should not be updated.
In practice, it is much more common to want to set a property on a CDR in
the h extension or in a hangup handler. Disallowing a common scenario to make
an esoteric behaviour work isn't good. This patch fixes this by allowing
callers to set a property IF we are the last CDR in the chain. This preserves
the finalized CDR if it was forked, while allowing the more common case to
function.
ASTERISK-25458 #close
Change-Id: Icf3553c607b9f561152a41e6d8381d594ccdf4b9
											 
										 
										
											2016-01-02 10:26:04 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( it_cdr - > fn_table  = =  & finalized_state_fn_table  & &  it_cdr - > next  ! =  NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2010-09-16 19:55:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! strcasecmp ( channel_name ,  it_cdr - > party_a . snapshot - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												headp  =  & it_cdr - > party_a . variables ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											}  else  if  ( it_cdr - > party_b . snapshot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												& &  ! strcasecmp ( channel_name ,  it_cdr - > party_b . snapshot - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												headp  =  & it_cdr - > party_b . variables ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-09-16 19:55:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( headp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												set_variable ( headp ,  name ,  value ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-10 05:41:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_iterator_destroy ( it_cdrs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-10 05:41:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Format  a  variable  on  a  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_object_format_var_internal ( struct  cdr_object  * cdr ,  const  char  * name ,  char  * value ,  size_t  length )  
						 
					
						
							
								
									
										
										
										
											2007-03-30 14:37:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_var_t  * variable ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-23 03:32:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_LIST_TRAVERSE ( & cdr - > party_a . variables ,  variable ,  entries )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strcasecmp ( name ,  ast_var_name ( variable ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_copy_string ( value ,  ast_var_value ( variable ) ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-23 03:32:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* value  =  ' \0 ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Format  one  of  the  standard  properties  on  a  \ ref  cdr_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  cdr_object_format_property ( struct  cdr_object  * cdr_obj ,  const  char  * name ,  char  * value ,  size_t  length )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * party_a  =  cdr_obj - > party_a . snapshot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_channel_snapshot  * party_b  =  cdr_obj - > party_b . snapshot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! strcasecmp ( name ,  " clid " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_callerid_merge ( value ,  length ,  party_a - > caller_name ,  party_a - > caller_number ,  " " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " src " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  party_a - > caller_number ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " dst " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  party_a - > exten ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " dcontext " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  party_a - > context ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " channel " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  party_a - > name ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " dstchannel " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( party_b )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_copy_string ( value ,  party_b - > name ,  length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-10 05:41:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_copy_string ( value ,  " " ,  length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-10 05:41:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " lastapp " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  party_a - > appl ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " lastdata " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  party_a - > data ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " start " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_get_tv ( cdr_obj - > start ,  NULL ,  value ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " answer " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_get_tv ( cdr_obj - > answer ,  NULL ,  value ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " end " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_get_tv ( cdr_obj - > end ,  NULL ,  value ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " duration " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										snprintf ( value ,  length ,  " %ld " ,  cdr_object_get_duration ( cdr_obj ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " billsec " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										snprintf ( value ,  length ,  " %ld " ,  cdr_object_get_billsec ( cdr_obj ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " disposition " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										snprintf ( value ,  length ,  " %u " ,  cdr_obj - > disposition ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " amaflags " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										snprintf ( value ,  length ,  " %d " ,  party_a - > amaflags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " accountcode " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  party_a - > accountcode ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " peeraccount " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( party_b )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_copy_string ( value ,  party_b - > accountcode ,  length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-30 14:37:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_copy_string ( value ,  " " ,  length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-03-22 21:43:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " uniqueid " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  party_a - > uniqueid ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " linkedid " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  cdr_obj - > linkedid ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " userfield " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_copy_string ( value ,  cdr_obj - > party_a . userfield ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( name ,  " sequence " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										snprintf ( value ,  length ,  " %u " ,  cdr_obj - > sequence ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2003-09-12 16:51:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-18 22:35:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \internal
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Look  up  and  retrieve  a  CDR  object  by  channel  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ param  name  The  name  of  the  channel 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  NULL  on  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ retval  The  \ ref  cdr_object  for  the  channel  on  success ,  with  the  reference 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	count  bumped  by  one . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  cdr_object  * cdr_object_get_by_name ( const  char  * name )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * param ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									param  =  ast_strdupa ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ao2_callback ( active_cdrs_by_channel ,  0 ,  cdr_object_get_by_name_cb ,  param ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_getvar ( const  char  * channel_name ,  const  char  * name ,  char  * value ,  size_t  length )  
						 
					
						
							
								
									
										
										
										
											2011-08-22 17:05:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  cdr_object_get_by_name ( channel_name ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * cdr_obj ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-08-22 17:05:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( AST_LOG_ERROR ,  " Unable to find CDR for channel %s \n " ,  channel_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-08-22 17:05:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_strlen_zero ( name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-08-22 17:05:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-24 19:03:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr_obj  =  cdr - > last ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr_object_format_property ( cdr_obj ,  name ,  value ,  length ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Property failed; attempt variable */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_format_var_internal ( cdr_obj ,  name ,  value ,  length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2003-09-12 16:51:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2003-09-12 16:51:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_serialize_variables ( const  char  * channel_name ,  struct  ast_str  * * buf ,  char  delim ,  char  sep )  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  cdr_object_get_by_name ( channel_name ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ast_var_t  * variable ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * var ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-05-15 16:54:26 +10:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  workspace [ 256 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  total  =  0 ,  x  =  0 ,  i ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-03 19:32:46 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_ENABLED ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( AST_LOG_ERROR ,  " Unable to find CDR for channel %s \n " ,  channel_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:56:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-05-21 15:33:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_str_reset ( * buf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-05-21 15:33:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( + + x  >  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_str_append ( buf ,  0 ,  " \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-05-21 15:33:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_LIST_TRAVERSE ( & it_cdr - > party_a . variables ,  variable ,  entries )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! ( var  =  ast_var_name ( variable ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-14 15:48:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ast_str_append ( buf ,  0 ,  " level %d: %s%c%s%c " ,  x ,  var ,  delim ,  S_OR ( ast_var_value ( variable ) ,  " " ) ,  sep )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_ERROR ,  " Data Buffer Size Exceeded! \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-14 15:48:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											total + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  ( i  =  0 ;  cdr_readonly_vars [ i ] ;  i + + )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:56:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( cdr_object_format_property ( it_cdr ,  cdr_readonly_vars [ i ] ,  workspace ,  sizeof ( workspace ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* Unhandled read-only CDR variable. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_assert ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2010-01-20 17:49:30 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! ast_strlen_zero ( workspace ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												& &  ast_str_append ( buf ,  0 ,  " level %d: %s%c%s%c " ,  x ,  cdr_readonly_vars [ i ] ,  delim ,  workspace ,  sep )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_log ( LOG_ERROR ,  " Data Buffer Size Exceeded! \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											total + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2003-02-02 19:44:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 00:16:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  total ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-03 21:21:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_cdr_free ( struct  ast_cdr  * cdr )  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  ast_cdr  * next  =  cdr - > next ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										free_variables ( & cdr - > varshead ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_free ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr  =  next ; 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ast_cdr  * ast_cdr_alloc ( void )  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_cdr  * x ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									x  =  ast_calloc ( 1 ,  sizeof ( * x ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  x ; 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  char  * ast_cdr_disp2str ( int  disposition )  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( disposition )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-18 22:35:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_CDR_NULL : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  " NO ANSWER " ;  /* by default, for backward compatibility */ 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  AST_CDR_NOANSWER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  " NO ANSWER " ; 
							 
						 
					
						
							
								
									
										
										
										
											2003-09-12 16:51:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_CDR_FAILED : 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  " FAILED " ; 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  AST_CDR_BUSY : 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  " BUSY " ; 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  AST_CDR_ANSWERED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  " ANSWERED " ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-08-22 17:05:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  AST_CDR_CONGESTION : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  " CONGESTION " ; 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  " UNKNOWN " ; 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  party_b_userfield_update  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * channel_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  char  * userfield ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Callback used to update the userfield on Party B on all CDRs */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  cdr_object_update_party_b_userfield_cb ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
									
										
										
										
											2002-07-29 22:40:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * cdr  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  party_b_userfield_update  * info  =  arg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-21 14:32:06 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( it_cdr - > fn_table  = =  & finalized_state_fn_table  & &  it_cdr - > next  ! =  NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( it_cdr - > party_b . snapshot 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:35:25 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											& &  ! strcasecmp ( it_cdr - > party_b . snapshot - > name ,  info - > channel_name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											strcpy ( it_cdr - > party_b . userfield ,  info - > userfield ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-13 21:22:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2004-06-20 15:19:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-26 15:28:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  ast_cdr_setuserfield ( const  char  * channel_name ,  const  char  * userfield )  
						 
					
						
							
								
									
										
										
										
											2009-06-26 15:28:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  cdr_object_get_by_name ( channel_name ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  party_b_userfield_update  party_b_info  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											. channel_name  =  channel_name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											. userfield  =  userfield , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-26 15:28:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Handle Party A */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-21 14:32:06 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( it_cdr - > fn_table  = =  & finalized_state_fn_table  & &  it_cdr - > next  ! =  NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-27 10:03:49 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_copy_string ( it_cdr - > party_a . userfield ,  userfield ,  AST_MAX_USER_FIELD ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-26 15:28:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-26 15:28:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Handle Party B */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_callback ( active_cdrs_by_channel ,  OBJ_NODATA , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_object_update_party_b_userfield_cb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											& party_b_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2002-07-29 22:40:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  post_cdr ( struct  ast_cdr  * cdr )  
						 
					
						
							
								
									
										
										
										
											2004-06-28 03:48:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_beitem  * i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( ;  cdr  ;  cdr  =  cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* For people, who don't want to see unanswered single-channel events */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_UNANSWERED )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr - > disposition  <  AST_CDR_ANSWERED  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												( ast_strlen_zero ( cdr - > channel )  | |  ast_strlen_zero ( cdr - > dstchannel ) ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " Skipping CDR  for %s since we weren't answered \n " ,  cdr - > channel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-21 22:41:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-19 17:14:32 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Modify CDR's */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_RWLIST_RDLOCK ( & mo_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_RWLIST_TRAVERSE ( & mo_list ,  i ,  list )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											i - > be ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_RWLIST_UNLOCK ( & mo_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ast_test_flag ( cdr ,  AST_CDR_FLAG_DISABLE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_RWLIST_RDLOCK ( & be_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_RWLIST_TRAVERSE ( & be_list ,  i ,  list )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! i - > suspended )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												i - > be ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AST_RWLIST_UNLOCK ( & be_list ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2004-06-28 03:48:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_set_property ( const  char  * channel_name ,  enum  ast_cdr_options  option )  
						 
					
						
							
								
									
										
										
										
											2004-01-11 03:23:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  cdr_object_get_by_name ( channel_name ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2004-01-11 03:23:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( it_cdr - > fn_table  = =  & finalized_state_fn_table )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Note: in general, set the flags on both the CDR record as well as the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Party  A .  Sometimes  all  we  have  is  the  Party  A  to  look  at . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_set_flag ( & it_cdr - > flags ,  option ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_set_flag ( & it_cdr - > party_a ,  option ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2004-06-20 15:19:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2004-01-11 03:23:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_clear_property ( const  char  * channel_name ,  enum  ast_cdr_options  option )  
						 
					
						
							
								
									
										
										
										
											2004-01-11 03:23:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  cdr_object_get_by_name ( channel_name ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2004-01-11 03:23:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( it_cdr - > fn_table  = =  & finalized_state_fn_table )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_clear_flag ( & it_cdr - > flags ,  option ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2004-01-11 03:23:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2004-01-11 03:23:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												app_cdr,app_forkcdr,func_cdr: Synchronize with engine when manipulating state
When doing the rework of the CDR engine that pushed all of the logic into cdr.c
and made it respond to changes in channel state over Stasis, we knew that
accessing the CDR engine from the dialplan would be "slightly"
non-deterministic. Dialplan threads would be accessing CDRs while Stasis
threads would be updating the state of said CDRs - whereas in the past,
everything happened on the dialplan threads. Tests have shown that "slightly"
is in reality "very".
This patch synchronizes things by making the dialplan applications/functions
that manipulate CDRs do so over Stasis. ForkCDR, NoCDR, ResetCDR, CDR, and
CDR_PROP now all use Stasis to send their requests over to the CDR engine,
and synchronize on the channel Stasis topic via a subscription so that they
return their values/control to the dialplan at the appropriate time.
While going through this, the following changes were also made:
 * DISA, which can reset the CDR when a user successfully authenticates, now
   just uses the ResetCDR app to do this. This prevents having to duplicate
   the same Stasis synchronization logic in that application.
 * Answer no longer disables CDRs. It actually didn't work anyway - calling
   DISABLE on the channel's CDR doesn't stop the CDR from getting the Answer
   time - it just kills all CDRs on that channel, which isn't what the caller
   would intend.
(closes issue ASTERISK-22884)
(closes issue ASTERISK-22886)
Review: https://reviewboard.asterisk.org/r/3057/
........
Merged revisions 404294 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404295 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-12-19 00:50:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_reset ( const  char  * channel_name ,  int  keep_variables )  
						 
					
						
							
								
									
										
										
										
											2003-02-02 19:44:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  cdr_object_get_by_name ( channel_name ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  ast_var_t  * vardata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2004-10-02 00:58:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-26 15:28:53 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* clear variables */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												app_cdr,app_forkcdr,func_cdr: Synchronize with engine when manipulating state
When doing the rework of the CDR engine that pushed all of the logic into cdr.c
and made it respond to changes in channel state over Stasis, we knew that
accessing the CDR engine from the dialplan would be "slightly"
non-deterministic. Dialplan threads would be accessing CDRs while Stasis
threads would be updating the state of said CDRs - whereas in the past,
everything happened on the dialplan threads. Tests have shown that "slightly"
is in reality "very".
This patch synchronizes things by making the dialplan applications/functions
that manipulate CDRs do so over Stasis. ForkCDR, NoCDR, ResetCDR, CDR, and
CDR_PROP now all use Stasis to send their requests over to the CDR engine,
and synchronize on the channel Stasis topic via a subscription so that they
return their values/control to the dialplan at the appropriate time.
While going through this, the following changes were also made:
 * DISA, which can reset the CDR when a user successfully authenticates, now
   just uses the ResetCDR app to do this. This prevents having to duplicate
   the same Stasis synchronization logic in that application.
 * Answer no longer disables CDRs. It actually didn't work anyway - calling
   DISABLE on the channel's CDR doesn't stop the CDR from getting the Answer
   time - it just kills all CDRs on that channel, which isn't what the caller
   would intend.
(closes issue ASTERISK-22884)
(closes issue ASTERISK-22886)
Review: https://reviewboard.asterisk.org/r/3057/
........
Merged revisions 404294 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404295 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-12-19 00:50:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! keep_variables )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											while  ( ( vardata  =  AST_LIST_REMOVE_HEAD ( & it_cdr - > party_a . variables ,  entries ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ast_var_delete ( vardata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( cdr - > party_b . snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												while  ( ( vardata  =  AST_LIST_REMOVE_HEAD ( & it_cdr - > party_b . variables ,  entries ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ast_var_delete ( vardata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2003-09-17 04:21:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Reset to initial state */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memset ( & it_cdr - > start ,  0 ,  sizeof ( it_cdr - > start ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memset ( & it_cdr - > end ,  0 ,  sizeof ( it_cdr - > end ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memset ( & it_cdr - > answer ,  0 ,  sizeof ( it_cdr - > answer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										it_cdr - > start  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_check_party_a_answer ( it_cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2003-02-02 19:44:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2004-06-20 22:46:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2003-02-02 19:44:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_fork ( const  char  * channel_name ,  struct  ast_flags  * options )  
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Fix a performance problem CDRs
There is a large performance price currently in the CDR engine. We currently
perform two ao2_callback calls on a container that has an entry for every
channel in the system. This is done to create matching pairs between channels
in a bridge.
As such, the portion of the CDR logic that this patch deals with is how we
make pairings when a channel enters a mixing bridge. In general, when a
channel enters such a bridge, we need to do two things:
 (1) Figure out if anyone in the bridge can be this channel's Party B.
 (2) Make pairings with every other channel in the bridge that is not already
     our Party B.
This is a two step process. In the first step, we look through everyone in the
bridge and see if they can be our Party B (single_state_process_bridge_enter).
If they can - yay! We mark our CDR as having gotten a Party B. If not, we keep
searching. If we don't find one, we wait until someone joins who can be our
Party B.
Step 2 is where we changed the logic
(handle_bridge_pairings and bridge_candidate_process). Previously, we would
first find candidates - those channels in the bridge with us - from the
active_cdrs_by_channel container. Because a channel could be a candidate if it
was Party B to an item in the container, the code implemented multiple
ao2_container callbacks to get all the candidates. We also had to store them
in another container with some other meta information. This was rather complex
and costly, particularly if you have 300 Local channels (600 channels!) going
at once.
Luckily, none of it is needed: when a channel enters a bridge (which is when
we're figuring all this stuff out), the bridge snapshot tells us the unique
IDs of everyone already in the bridge. All we need to do is:
 For all channels in the bridge:
   If the channel is us or our Party B that we got in step 1, skip it
   Compare us and the candidate to figure out who is Party A (based on some
       specific rules)
   If we are Party A:
      Make a new CDR for us, append it to our chain, and set the candidate as
          Party B
   If they are Party A:
      If they don't have a Party B:
        Make a new CDR for them, append us to their chain, and us as Party B
      Otherwise:
        Copy us over as Party B on their existing CDR.
This patch does that.
Because we now use channel unique IDs to find the candidates during bridging,
active_cdrs_by_channel now looks up things using uniqueid instead of channel
name. This makes the more complex code simpler; it does, however, have the
drawback that dialplan applications and functions will be slightly slower as
they have to iterate through the container looking for the CDR by name.
That's a small price to pay however as the bridging code will be called a lot
more often.
This patch also does two other minor changes:
 (1) It reduces the container size of the channels in a bridge snapshot to 1.
     In order to be predictable for multi-party bridges, the order of the
     channels in the container must be stable; that is, it must always devolve
     to a linked list.
 (2) CDRs and the multi-party test was updated to show the relationship between
     two dialed channels. You still want to know if they talked - previously,
     dialed channels were always ignored, which is wrong when they have
     managed to get a Party B.
(closes issue ASTERISK-22488)
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/2861/
........
Merged revisions 399666 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@399667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-09-24 18:10:20 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  cdr_object_get_by_name ( channel_name ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * new_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr_obj ; 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										SCOPED_AO2LOCK ( lock ,  cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-03-13 21:27:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_obj  =  cdr - > last ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cdr_obj - > fn_table  = =  & finalized_state_fn_table )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If the last CDR in the chain is finalized, don't allow a fork -
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  things  are  already  dying  at  this  point 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-03-10 14:36:16 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Copy over the basic CDR information. The Party A information is
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  copied  over  automatically  as  part  of  the  append 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Forking CDR for channel %s \n " ,  cdr - > party_a . snapshot - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_cdr  =  cdr_object_create_and_append ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! new_cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-05-29 19:04:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										new_cdr - > fn_table  =  cdr_obj - > fn_table ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_string_field_set ( new_cdr ,  bridge ,  cdr - > bridge ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-09-06 22:50:24 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_string_field_set ( new_cdr ,  appl ,  cdr - > appl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_string_field_set ( new_cdr ,  data ,  cdr - > data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_string_field_set ( new_cdr ,  context ,  cdr - > context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_string_field_set ( new_cdr ,  exten ,  cdr - > exten ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										new_cdr - > flags  =  cdr - > flags ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Explicitly clear the AST_CDR_LOCK_APP flag - we want
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  the  application  to  be  changed  on  the  new  CDR  if  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  dialplan  demands  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_clear_flag ( & new_cdr - > flags ,  AST_CDR_LOCK_APP ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If there's a Party B, copy it over as well */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cdr_obj - > party_b . snapshot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											new_cdr - > party_b . snapshot  =  cdr_obj - > party_b . snapshot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ao2_ref ( new_cdr - > party_b . snapshot ,  + 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											strcpy ( new_cdr - > party_b . userfield ,  cdr_obj - > party_b . userfield ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											new_cdr - > party_b . flags  =  cdr_obj - > party_b . flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ast_test_flag ( options ,  AST_CDR_FLAG_KEEP_VARS ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												copy_variables ( & new_cdr - > party_b . variables ,  & cdr_obj - > party_b . variables ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2001-10-18 15:38:46 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										new_cdr - > start  =  cdr_obj - > start ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										new_cdr - > answer  =  cdr_obj - > answer ; 
							 
						 
					
						
							
								
									
										
										
										
											2003-02-02 19:44:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Modify the times based on the flags passed in */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( options ,  AST_CDR_FLAG_SET_ANSWER ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												& &  new_cdr - > party_a . snapshot - > state  = =  AST_STATE_UP )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											new_cdr - > answer  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( options ,  AST_CDR_FLAG_RESET ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											new_cdr - > answer  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											new_cdr - > start  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Create and append, by default, copies over the variables */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ast_test_flag ( options ,  AST_CDR_FLAG_KEEP_VARS ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											free_variables ( & new_cdr - > party_a . variables ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-17 00:37:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Finalize any current CDRs */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( options ,  AST_CDR_FLAG_FINALIZE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  ( it_cdr  =  cdr ;  it_cdr  ! =  new_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( it_cdr - > fn_table  = =  & finalized_state_fn_table )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-17 00:37:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												/* Force finalization on the CDR. This will bypass any checks for
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  end  before  ' h '  extension . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr_object_finalize ( it_cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cdr_object_transition_state ( it_cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-02-23 22:48:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2003-09-17 04:21:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2003-02-02 19:44:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-15 02:42:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2004-06-20 22:46:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-11-14 19:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \note Don't call without cdr_batch_lock */  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  reset_batch ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									batch - > size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									batch - > head  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									batch - > tail  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-11-14 19:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \note Don't call without cdr_batch_lock */  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  init_batch ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-06 16:01:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ( batch  =  ast_malloc ( sizeof ( * batch ) ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									reset_batch ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * do_batch_backend_process ( void  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_batch_item  * processeditem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_batch_item  * batchitem  =  data ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Push each CDR into storage mechanism(s) and free all the memory */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( batchitem )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										post_cdr ( batchitem - > cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cdr_free ( batchitem - > cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										processeditem  =  batchitem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										batchitem  =  batchitem - > next ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-06 21:20:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_free ( processeditem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  cdr_submit_batch ( int  do_shutdown )  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_batch_item  * oldbatchitems  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									pthread_t  batch_post_thread  =  AST_PTHREADT_NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* if there's no batch, or no CDRs in the batch, then there's nothing to do */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! batch  | |  ! batch - > head )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* move the old CDRs aside, and prepare a new CDR batch */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_lock ( & cdr_batch_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									oldbatchitems  =  batch - > head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									reset_batch ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_unlock ( & cdr_batch_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* if configured, spawn a new thread to post these CDRs,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   also  try  to  save  as  much  as  possible  if  we  are  shutting  down  safely  */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & mod_cfg - > general - > batch_settings . settings ,  BATCH_MODE_SCHEDULER_ONLY )  | |  do_shutdown )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-14 19:39:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " CDR single-threaded batch processing begins now \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										do_batch_backend_process ( oldbatchitems ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-24 18:30:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ast_pthread_create_detached_background ( & batch_post_thread ,  NULL ,  do_batch_backend_process ,  oldbatchitems ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_log ( LOG_WARNING ,  " CDR processing thread could not detach, now trying in this thread \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											do_batch_backend_process ( oldbatchitems ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-14 19:39:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_debug ( 1 ,  " CDR multi-threaded batch processing begins now \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-09-21 14:40:10 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  submit_scheduled_batch ( const  void  * data )  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_submit_batch ( 0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* manually reschedule from this point in time */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-03-26 01:58:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_mutex_lock ( & cdr_sched_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-16 21:21:44 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr_sched  =  ast_sched_add ( sched ,  mod_cfg - > general - > batch_settings . time  *  1000 ,  submit_scheduled_batch ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-03-26 01:58:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_mutex_unlock ( & cdr_sched_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* returning zero so the scheduler does not automatically reschedule */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-03-26 01:58:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! Do not hold the batch lock while calling this function */  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  submit_unscheduled_batch ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-03-26 01:58:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Prevent two deletes from happening at the same time */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_lock ( & cdr_sched_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* this is okay since we are not being called from within the scheduler */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-01-27 22:35:29 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									AST_SCHED_DEL ( sched ,  cdr_sched ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* schedule the submission to occur ASAP (1 ms) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_sched  =  ast_sched_add ( sched ,  1 ,  submit_scheduled_batch ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-03-26 01:58:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_mutex_unlock ( & cdr_sched_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-14 14:45:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_mutex_lock ( & cdr_pending_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-10-28 16:35:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cond_signal ( & cdr_pending_cond ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-14 14:45:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_mutex_unlock ( & cdr_pending_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  cdr_detach ( struct  ast_cdr  * cdr )  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_batch_item  * newtail ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  curr ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-03-26 01:58:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  submit_batch  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-30 17:57:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-30 17:57:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* maybe they disabled CDR stuff completely, so just drop it */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_ENABLED ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-14 19:39:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " Dropping CDR ! \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_cdr_free ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* post stuff immediately if we are not in batch mode, this is legacy behaviour */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_BATCHMODE ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										post_cdr ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cdr_free ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* otherwise, each CDR gets put into a batch list (at the end) */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-14 19:39:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_debug ( 1 ,  " CDR detaching from this thread \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-04-06 16:01:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* we'll need a new tail for every CDR */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-15 01:48:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ( newtail  =  ast_calloc ( 1 ,  sizeof ( * newtail ) ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										post_cdr ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cdr_free ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* don't traverse a whole list (just keep track of the tail) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_lock ( & cdr_batch_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! batch ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										init_batch ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! batch - > head )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* new batch is empty, so point the head at the new tail */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										batch - > head  =  newtail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* already got a batch with something in it, so just append a new tail */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										batch - > tail - > next  =  newtail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									newtail - > cdr  =  cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									batch - > tail  =  newtail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									curr  =  batch - > size + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* if we have enough stuff to post, then do it */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( curr  > =  ( mod_cfg - > general - > batch_settings . size  -  1 ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-03-26 01:58:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										submit_batch  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-11-04 00:02:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_mutex_unlock ( & cdr_batch_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-03-26 01:58:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Don't call submit_unscheduled_batch with the cdr_batch_lock held */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( submit_batch )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										submit_unscheduled_batch ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  * do_cdr ( void  * data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  timespec  timeout ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  schedms ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  numevents  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-01-23 00:11:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( ; ; )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-09-07 16:33:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  timeval  now ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										schedms  =  ast_sched_wait ( sched ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* this shouldn't happen, but provide a 1 second default just in case */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( schedms  < =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											schedms  =  1000 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-09-07 16:33:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										now  =  ast_tvadd ( ast_tvnow ( ) ,  ast_samp2tv ( schedms ,  1000 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										timeout . tv_sec  =  now . tv_sec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										timeout . tv_nsec  =  now . tv_usec  *  1000 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-14 14:45:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_mutex_lock ( & cdr_pending_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-10-28 16:35:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_cond_timedwait ( & cdr_pending_cond ,  & cdr_pending_lock ,  & timeout ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										numevents  =  ast_sched_runq ( sched ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-14 14:45:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_mutex_unlock ( & cdr_pending_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-14 19:39:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 2 ,  " Processed %d scheduled CDR batches from the run queue \n " ,  numevents ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * handle_cli_debug ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " cdr set debug [on|off] " ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										e - > usage  =  " Enable or disable extra debugging in the CDR Engine. Note \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" that this will dump debug information to the VERBOSE setting \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" and should only be used when debugging information from the \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" CDR engine is needed. \n " ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( a - > argc  ! =  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:43:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! strcasecmp ( a - > argv [ 3 ] ,  " on " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ! ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_DEBUG ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_set_flag ( & mod_cfg - > general - > settings ,  CDR_DEBUG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " CDR debugging enabled \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 22:43:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  if  ( ! strcasecmp ( a - > argv [ 3 ] ,  " off " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										& &  ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_DEBUG ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_clear_flag ( & mod_cfg - > general - > settings ,  CDR_DEBUG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " CDR debugging disabled \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*! \brief Complete user input for 'cdr show' */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  * cli_complete_show ( struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  * result  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  wordlen  =  strlen ( a - > word ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  which  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_iterator  it_cdrs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									it_cdrs  =  ao2_iterator_init ( active_cdrs_by_channel ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( cdr  =  ao2_iterator_next ( & it_cdrs ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! strncasecmp ( a - > word ,  cdr - > party_a . snapshot - > name ,  wordlen )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( + + which  >  a - > n ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											result  =  ast_strdup ( cdr - > party_a . snapshot - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ao2_ref ( cdr ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_ref ( cdr ,  - 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & it_cdrs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cli_show_channels ( struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  ao2_iterator  it_cdrs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  start_time_buffer [ 64 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 23:15:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  answer_time_buffer [ 64 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  end_time_buffer [ 64 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define TITLE_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define FORMAT_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Channels with Call Detail Record (CDR) Information \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " -------------------------------------------------- \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  TITLE_STRING ,  " Channel " ,  " Dst. Channel " ,  " LastApp " ,  " Start " ,  " Answer " ,  " End " ,  " Billsec " ,  " Duration " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									it_cdrs  =  ao2_iterator_init ( active_cdrs_by_channel ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-06 12:45:39 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( ;  ( cdr  =  ao2_iterator_next ( & it_cdrs ) ) ;  ao2_cleanup ( cdr ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  timeval  start_time  =  {  0 ,  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  timeval  answer_time  =  {  0 ,  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  timeval  end_time  =  {  0 ,  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										SCOPED_AO2LOCK ( lock ,  cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Calculate the start, end, answer, billsec, and duration over the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  life  of  all  of  the  CDR  entries 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( snapshot_is_dialed ( it_cdr - > party_a . snapshot ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ast_tvzero ( start_time ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												start_time  =  it_cdr - > start ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! ast_tvzero ( it_cdr - > answer )  & &  ast_tvzero ( answer_time ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												answer_time  =  it_cdr - > answer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If there was no start time, then all CDRs were for a dialed channel; skip */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ast_tvzero ( start_time ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										it_cdr  =  cdr - > last ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										end_time  =  ast_tvzero ( it_cdr - > end )  ?  ast_tvnow ( )  :  it_cdr - > end ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										cdr_get_tv ( start_time ,  " %T " ,  start_time_buffer ,  sizeof ( start_time_buffer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_get_tv ( answer_time ,  " %T " ,  answer_time_buffer ,  sizeof ( answer_time_buffer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_get_tv ( end_time ,  " %T " ,  end_time_buffer ,  sizeof ( end_time_buffer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  FORMAT_STRING ,  it_cdr - > party_a . snapshot - > name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												it_cdr - > party_b . snapshot  ?  it_cdr - > party_b . snapshot - > name  :  " <none> " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												it_cdr - > appl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												start_time_buffer , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												answer_time_buffer , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												end_time_buffer , 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_tvzero ( answer_time )  ?  0  :  ( long ) ast_tvdiff_ms ( end_time ,  answer_time )  /  1000 , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												( long ) ast_tvdiff_ms ( end_time ,  start_time )  /  1000 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_iterator_destroy ( & it_cdrs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef FORMAT_STRING 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef TITLE_STRING 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cli_show_channel ( struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  clid [ 64 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  start_time_buffer [ 64 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-28 23:15:43 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  answer_time_buffer [ 64 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  end_time_buffer [ 64 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  char  * channel_name  =  a - > argv [ 3 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  cdr_object  * ,  cdr ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define TITLE_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define FORMAT_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 19:17:15 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr  =  cdr_object_get_by_name ( channel_name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Unknown channel: %s \n " ,  channel_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Call Detail Record (CDR) Information for %s \n " ,  channel_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " -------------------------------------------------- \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  TITLE_STRING ,  " AccountCode " ,  " CallerID " ,  " Dst. Channel " ,  " LastApp " ,  " Data " ,  " Start " ,  " Answer " ,  " End " ,  " Billsec " ,  " Duration " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  timeval  end ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( snapshot_is_dialed ( it_cdr - > party_a . snapshot ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_callerid_merge ( clid ,  sizeof ( clid ) ,  it_cdr - > party_a . snapshot - > caller_name ,  it_cdr - > party_a . snapshot - > caller_number ,  " " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_tvzero ( it_cdr - > end ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											end  =  ast_tvnow ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											end  =  it_cdr - > end ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_get_tv ( it_cdr - > start ,  " %T " ,  start_time_buffer ,  sizeof ( start_time_buffer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_get_tv ( it_cdr - > answer ,  " %T " ,  answer_time_buffer ,  sizeof ( answer_time_buffer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_get_tv ( end ,  " %T " ,  end_time_buffer ,  sizeof ( end_time_buffer ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  FORMAT_STRING , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												it_cdr - > party_a . snapshot - > accountcode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												clid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												it_cdr - > party_b . snapshot  ?  it_cdr - > party_b . snapshot - > name  :  " <none> " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												it_cdr - > appl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												it_cdr - > data , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												start_time_buffer , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												answer_time_buffer , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												end_time_buffer , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												( long ) ast_tvdiff_ms ( end ,  it_cdr - > answer )  /  1000 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												( long ) ast_tvdiff_ms ( end ,  it_cdr - > start )  /  1000 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef FORMAT_STRING 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef TITLE_STRING 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  char  * handle_cli_show ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											e - > command  =  " cdr show active " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											e - > usage  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" Usage: cdr show active [channel] \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" 	Displays a summary of all Call Detail Records when [channel] \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" 	is omitted; displays all of the Call Detail Records \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" 	currently in flight for a given [channel] when [channel] is \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" 	specified. \n \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" 	Note that this will not display Call Detail Records that \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" 	have already been dispatched to a backend storage, nor for \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												" 	channels that are no longer active. \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  cli_complete_show ( a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( a - > argc  >  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( a - > argc  <  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cli_show_channels ( a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cli_show_channel ( a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * handle_cli_status ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_beitem  * beitem  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  cnt  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									long  nextbatchtime  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-08 21:26:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										e - > command  =  " cdr show status " ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-08 21:26:32 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" Usage: cdr show status \n " 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" 	Displays the Call Detail Record engine system status. \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( a - > argc  >  3 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-06-27 23:29:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Call Detail Record (CDR) settings \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " ---------------------------------- \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  "   Logging:                    %s \n " ,  ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_ENABLED )  ?  " Enabled "  :  " Disabled " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  "   Mode:                       %s \n " ,  ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_BATCHMODE )  ?  " Batch "  :  " Simple " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_ENABLED ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  "   Log unanswered calls:       %s \n " ,  ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_UNANSWERED )  ?  " Yes "  :  " No " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  "   Log congestion:             %s \n \n " ,  ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_CONGESTION )  ?  " Yes "  :  " No " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_BATCHMODE ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-06-27 23:29:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  " * Batch Mode Settings \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  "   ------------------- \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( batch ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cnt  =  batch - > size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( cdr_sched  >  - 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												nextbatchtime  =  ast_sched_when ( sched ,  cdr_sched ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  "   Safe shutdown:              %s \n " ,  ast_test_flag ( & mod_cfg - > general - > batch_settings . settings ,  BATCH_MODE_SAFE_SHUTDOWN )  ?  " Enabled "  :  " Disabled " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  "   Threading model:            %s \n " ,  ast_test_flag ( & mod_cfg - > general - > batch_settings . settings ,  BATCH_MODE_SCHEDULER_ONLY )  ?  " Scheduler only "  :  " Scheduler plus separate threads " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-06-27 23:29:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  "   Current batch size:         %d record%s \n " ,  cnt ,  ESS ( cnt ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  "   Maximum batch size:         %u record%s \n " ,  mod_cfg - > general - > batch_settings . size ,  ESS ( mod_cfg - > general - > batch_settings . size ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  "   Maximum batch time:         %u second%s \n " ,  mod_cfg - > general - > batch_settings . time ,  ESS ( mod_cfg - > general - > batch_settings . time ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-06-27 23:29:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  "   Next batch processing time: %ld second%s \n \n " ,  nextbatchtime ,  ESS ( nextbatchtime ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2008-06-27 23:29:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " * Registered Backends \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  "   ------------------- \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-18 16:37:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_RWLIST_RDLOCK ( & be_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-06-27 23:29:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( AST_RWLIST_EMPTY ( & be_list ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_cli ( a - > fd ,  "     (none) \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AST_RWLIST_TRAVERSE ( & be_list ,  beitem ,  list )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-27 20:04:17 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												ast_cli ( a - > fd ,  "     %s%s \n " ,  beitem - > name ,  beitem - > suspended  ?  "  (suspended)  "  :  " " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-06-27 23:29:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-18 16:37:14 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										AST_RWLIST_UNLOCK ( & be_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-06-27 23:29:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  * handle_cli_submit ( struct  ast_cli_entry  * e ,  int  cmd ,  struct  ast_cli_args  * a )  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										e - > command  =  " cdr submit " ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-26 08:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										e - > usage  = 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" Usage: cdr submit \n " 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" Posts all pending batched CDR data to the configured CDR \n " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											" backend engine modules. \n " ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  CLI_GENERATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( a - > argc  >  2 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  CLI_SHOWUSAGE ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_ENABLED ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Cannot submit CDR batch: CDR engine disabled. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_BATCHMODE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cli ( a - > fd ,  " Cannot submit CDR batch: batch mode not enabled. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									submit_unscheduled_batch ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli ( a - > fd ,  " Submitted CDRs to backend engines for processing.  This may take a while. \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-10-11 19:03:06 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  CLI_SUCCESS ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  struct  ast_cli_entry  cli_commands [ ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_cli_submit ,  " Posts all pending batched CDR data " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_cli_status ,  " Display the CDR status " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_cli_show ,  " Display active CDRs for channels " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_CLI_DEFINE ( handle_cli_debug ,  " Enable debugging in the CDR engine " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  This  dispatches  * all *  \ ref  cdr_objects .  It  should  only  be  used  during 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  shutdown ,  so  that  we  get  billing  records  for  everything  that  we  can . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  cdr_object_dispatch_all_cb ( void  * obj ,  void  * arg ,  int  flags )  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cdr_object  * cdr  =  obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-16 21:09:46 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 18:22:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_lock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_transition_state ( it_cdr ,  & finalized_state_fn_table ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-09-12 23:30:03 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr_object_dispatch ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 18:22:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_unlock ( cdr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2010-08-05 13:19:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  finalize_batch_mode ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr_thread  = =  AST_PTHREADT_NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-03 18:45:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-08-05 13:19:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* wake up the thread so it will exit */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pthread_cancel ( cdr_thread ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pthread_kill ( cdr_thread ,  SIGURG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pthread_join ( cdr_thread ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_thread  =  AST_PTHREADT_NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cond_destroy ( & cdr_pending_cond ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_cdr_engine_term ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-01-12 22:13:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  stasis_message_router  * ast_cdr_message_router ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! stasis_router )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_bump ( stasis_router ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  stasis_router ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
									
										
										
										
											2014-01-12 22:13:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  \ brief  Destroy  the  active  Stasis  subscriptions 
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  destroy_subscriptions ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									channel_subscription  =  stasis_forward_cancel ( channel_subscription ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_subscription  =  stasis_forward_cancel ( bridge_subscription ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									parking_subscription  =  stasis_forward_cancel ( parking_subscription ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Create  the  Stasis  subcriptions  for  CDRs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  create_subscriptions ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr_topic )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-01-12 22:13:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( channel_subscription  | |  bridge_subscription  | |  parking_subscription )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									channel_subscription  =  stasis_forward_all ( ast_channel_topic_all_cached ( ) ,  cdr_topic ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! channel_subscription )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bridge_subscription  =  stasis_forward_all ( ast_bridge_topic_all_cached ( ) ,  cdr_topic ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! bridge_subscription )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									parking_subscription  =  stasis_forward_all ( ast_parking_topic ( ) ,  cdr_topic ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! parking_subscription )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  process_config ( int  reload )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  module_config_alloc ( ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! reload )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( aco_info_init ( & cfg_info ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " enable " ,  ACO_EXACT ,  general_options ,  DEFAULT_ENABLED ,  OPT_BOOLFLAG_T ,  1 ,  FLDSET ( struct  ast_cdr_config ,  settings ) ,  CDR_ENABLED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " debug " ,  ACO_EXACT ,  general_options ,  0 ,  OPT_BOOLFLAG_T ,  1 ,  FLDSET ( struct  ast_cdr_config ,  settings ) ,  CDR_DEBUG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " unanswered " ,  ACO_EXACT ,  general_options ,  DEFAULT_UNANSWERED ,  OPT_BOOLFLAG_T ,  1 ,  FLDSET ( struct  ast_cdr_config ,  settings ) ,  CDR_UNANSWERED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " congestion " ,  ACO_EXACT ,  general_options ,  0 ,  OPT_BOOLFLAG_T ,  1 ,  FLDSET ( struct  ast_cdr_config ,  settings ) ,  CDR_CONGESTION ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " batch " ,  ACO_EXACT ,  general_options ,  DEFAULT_BATCHMODE ,  OPT_BOOLFLAG_T ,  1 ,  FLDSET ( struct  ast_cdr_config ,  settings ) ,  CDR_BATCHMODE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " endbeforehexten " ,  ACO_EXACT ,  general_options ,  DEFAULT_END_BEFORE_H_EXTEN ,  OPT_BOOLFLAG_T ,  1 ,  FLDSET ( struct  ast_cdr_config ,  settings ) ,  CDR_END_BEFORE_H_EXTEN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " initiatedseconds " ,  ACO_EXACT ,  general_options ,  DEFAULT_INITIATED_SECONDS ,  OPT_BOOLFLAG_T ,  1 ,  FLDSET ( struct  ast_cdr_config ,  settings ) ,  CDR_INITIATED_SECONDS ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " scheduleronly " ,  ACO_EXACT ,  general_options ,  DEFAULT_BATCH_SCHEDULER_ONLY ,  OPT_BOOLFLAG_T ,  1 ,  FLDSET ( struct  ast_cdr_config ,  batch_settings . settings ) ,  BATCH_MODE_SCHEDULER_ONLY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " safeshutdown " ,  ACO_EXACT ,  general_options ,  DEFAULT_BATCH_SAFE_SHUTDOWN ,  OPT_BOOLFLAG_T ,  1 ,  FLDSET ( struct  ast_cdr_config ,  batch_settings . settings ) ,  BATCH_MODE_SAFE_SHUTDOWN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " size " ,  ACO_EXACT ,  general_options ,  DEFAULT_BATCH_SIZE ,  OPT_UINT_T ,  PARSE_IN_RANGE ,  FLDSET ( struct  ast_cdr_config ,  batch_settings . size ) ,  0 ,  MAX_BATCH_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aco_option_register ( & cfg_info ,  " time " ,  ACO_EXACT ,  general_options ,  DEFAULT_BATCH_TIME ,  OPT_UINT_T ,  PARSE_IN_RANGE ,  FLDSET ( struct  ast_cdr_config ,  batch_settings . time ) ,  0 ,  MAX_BATCH_TIME ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( aco_process_config ( & cfg_info ,  reload ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! mod_cfg )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If we couldn't process the configuration and this wasn't a reload,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  create  a  default  config 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! reload  & &  ! ( aco_set_defaults ( & general_option ,  " general " ,  mod_cfg - > general ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_NOTICE ,  " Failed to process CDR configuration; using defaults \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-06 19:26:48 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ao2_global_obj_replace_unref ( module_configs ,  mod_cfg ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-03 18:45:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 18:22:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  cdr_engine_cleanup ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									destroy_subscriptions ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 18:22:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-12-03 18:45:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  cdr_engine_shutdown ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2014-01-12 22:13:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									stasis_message_router_unsubscribe_and_join ( stasis_router ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									stasis_router  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_cleanup ( cdr_topic ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_topic  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									STASIS_MESSAGE_TYPE_CLEANUP ( cdr_sync_message_type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_callback ( active_cdrs_by_channel ,  OBJ_NODATA ,  cdr_object_dispatch_all_cb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									finalize_batch_mode ( ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli_unregister_multiple ( cli_commands ,  ARRAY_LEN ( cli_commands ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-03 18:45:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_sched_context_destroy ( sched ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sched  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ast_free ( batch ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									batch  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-24 23:56:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									aco_info_destroy ( & cfg_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ao2_global_obj_release ( module_configs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-06 20:03:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_container_unregister ( " cdrs_by_channel " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_ref ( active_cdrs_by_channel ,  - 1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-06 20:03:01 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									active_cdrs_by_channel  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_enable_batch_mode ( struct  ast_cdr_config  * config )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SCOPED_LOCK ( batch ,  & cdr_batch_lock ,  ast_mutex_lock ,  ast_mutex_unlock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Only create the thread level portions once */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cdr_thread  = =  AST_PTHREADT_NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_cond_init ( & cdr_pending_cond ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_pthread_create_background ( & cdr_thread ,  NULL ,  do_cdr ,  NULL )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_ERROR ,  " Unable to start CDR thread. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Kill the currently scheduled item */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									AST_SCHED_DEL ( sched ,  cdr_sched ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cdr_sched  =  ast_sched_add ( sched ,  config - > batch_settings . time  *  1000 ,  submit_scheduled_batch ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-05-09 22:49:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_log ( LOG_NOTICE ,  " CDR batch mode logging enabled, first of either size %u or time %u seconds. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											config - > batch_settings . size ,  config - > batch_settings . time ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ internal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Print  channel  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 . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ return  Nothing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  cdr_container_print_fn ( void  * v_obj ,  void  * where ,  ao2_prnt_fn  * prnt )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * cdr  =  v_obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cdr_object  * it_cdr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( it_cdr  =  cdr ;  it_cdr ;  it_cdr  =  it_cdr - > next )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										prnt ( where ,  " Party A: %s; Party B: %s; Bridge %s \n " ,  it_cdr - > party_a . snapshot - > name ,  it_cdr - > party_b . snapshot  ?  it_cdr - > party_b . snapshot - > name  :  " <unknown> " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												it_cdr - > bridge ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  \ brief  Checks  if  CDRs  are  enabled  and  enables / disables  the  necessary  options 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  cdr_toggle_runtime_options ( void )  
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_ENABLED ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( create_subscriptions ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											destroy_subscriptions ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( AST_LOG_ERROR ,  " Failed to create Stasis subscriptions \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_BATCHMODE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cdr_enable_batch_mode ( mod_cfg - > general ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ast_log ( LOG_NOTICE ,  " CDR simple logging enabled. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										destroy_subscriptions ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_NOTICE ,  " CDR logging disabled. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  ast_cdr_engine_init ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( process_config ( 0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-01-12 22:13:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cdr_topic  =  stasis_topic_create ( " cdr_engine " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! cdr_topic )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									stasis_router  =  stasis_message_router_create ( cdr_topic ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! stasis_router )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-06-03 11:35:49 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									stasis_message_router_set_congestion_limits ( stasis_router ,  - 1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										10  *  AST_TASKPROCESSOR_HIGH_WATER_LEVEL ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( STASIS_MESSAGE_TYPE_INIT ( cdr_sync_message_type ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-01-12 22:13:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									stasis_message_router_add_cache_update ( stasis_router ,  ast_channel_snapshot_type ( ) ,  handle_channel_cache_message ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									stasis_message_router_add ( stasis_router ,  ast_channel_dial_type ( ) ,  handle_dial_message ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									stasis_message_router_add ( stasis_router ,  ast_channel_entered_bridge_type ( ) ,  handle_bridge_enter_message ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									stasis_message_router_add ( stasis_router ,  ast_channel_left_bridge_type ( ) ,  handle_bridge_leave_message ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									stasis_message_router_add ( stasis_router ,  ast_parked_call_type ( ) ,  handle_parked_call_message ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									stasis_message_router_add ( stasis_router ,  cdr_sync_message_type ( ) ,  handle_cdr_sync_message ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-01-12 22:13:12 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-06 21:17:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									active_cdrs_by_channel  =  ao2_container_alloc ( NUM_CDR_BUCKETS , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_object_channel_hash_fn ,  cdr_object_channel_cmp_fn ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! active_cdrs_by_channel )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-03 22:04:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ao2_container_register ( " cdrs_by_channel " ,  active_cdrs_by_channel ,  cdr_container_print_fn ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-12-20 17:15:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									sched  =  ast_sched_context_create ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! sched )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ast_log ( LOG_ERROR ,  " Unable to create schedule context. \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Handle hangup logic in the Stasis message bus and consumers of Stasis messages
This patch does the following:
* It adds a new soft hangup flag AST_SOFTHANGUP_HANGUP_EXEC that is set when a
  channel is executing dialplan hangup logic, i.e., the 'h' extension or a
  hangup handler. Stasis messages now also convey the soft hangup flag so
  consumers of the messages can know when a channel is executing said
  hangup logic.
* It adds a new channel flag, AST_FLAG_DEAD, which is set when a channel is
  well and truly dead. Not just a zombie, but dead, Jim. Manager, CEL, CDRs,
  and other consumers of Stasis have been updated to look for this flag to
  know when the channel should by lying six feet under.
* The CDR engine has been updated to better handle a channel entering and
  leaving a bridge. Previously, a new CDR was automatically created when a
  channel left a bridge and put into the 'Pending' state; however, this
  way of handling CDRs made it difficult for the 'endbeforehexten' logic to
  work correctly - there was always a new CDR waiting in the hangup logic
  and, even if 'ended', wouldn't be the CDR people wanted to inspect in the
  hangup routine. This patch completely removes the Pending state and instead
  defers creation of the new CDR until it gets a new message that requires
  a new CDR.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2013-07-07 20:34:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_cli_register_multiple ( cli_commands ,  ARRAY_LEN ( cli_commands ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 18:22:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_register_cleanup ( cdr_engine_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-12-03 18:45:18 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ast_register_atexit ( cdr_engine_shutdown ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  cdr_toggle_runtime_options ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  ast_cdr_engine_term ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-06 12:55:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( void  * ,  payload ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  stasis_message  * ,  message ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Since this is called explicitly during process shutdown, we might not have ever
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  been  initialized .  If  so ,  the  config  object  will  be  NULL . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! mod_cfg )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-06 12:55:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( cdr_sync_message_type ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Make sure we have the needed items */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										payload  =  ao2_alloc ( sizeof ( * payload ) ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! stasis_router  | |  ! payload )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-06 12:55:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ast_debug ( 1 ,  " CDR Engine termination request received; waiting on messages... \n " ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-06 12:55:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										message  =  stasis_message_create ( cdr_sync_message_type ( ) ,  payload ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( message )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											stasis_message_router_publish_sync ( stasis_router ,  message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												CDRs: fix a variety of dial status problems, h/hangup handler creating CDRs
This patch fixes a number of small-ish problems that were noticed when
witnessing the records that the FreePBX dialplan produces:
(1) Mid-call events (as well as privacy options) have the ability to change the
    overall state of the Dial operation after the called party answers. This
    means that publishing the DialEnd event when the called party is premature;
    we have to wait for the execution of these subroutines to complete before
    we can signal the overall status of the DialEnd. This patch moves that
    publication and adds handlers for the mid-call events.
(2) The AST_FLAG_OUTGOING channel flag is cleared if an after bridge goto
    datastore is detected. This flag was preventing CDRs from being recorded
    for all outbound channels that had a 'continue' option enabled on them by
    the Dial application.
(3) The CDR engine now locks the 'Dial' application as being the CDR
    application if it detects that the current CDR has entered that app. This
    is similar to the logic that is done for Parking. In general, if we entered
    into Dial, then we want that CDR to record the application as such - this
    prevents pre-dial handlers, mid-call handlers, and other shenaniganry
    from changing the application value.
(4) The CDR engine now checks for the AST_SOFTHANGUP_HANGUP_EXEC in more places
    to determine if the channel is in hangup logic or dead. In either case, we
    don't want to record changes in the channel.
(5) The default option for "endbeforehexten" has been changed to "yes". In
    general, you don't want to see CDRs in the 'h' exten or in hangup logic.
    Since the semantics of that option changed in 12, it made sense to update
    the default value as well.
(6) Finally, because we now have the ability to synchronize on the messages
    published to the CDR topic, on shutdown the CDR engine will now synchronize
    to the messages currently in flight. This helps to ensure that all
    in-flight CDRs are written before shutting down.
(closes issue ASTERISK-23164)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3154
........
Merged revisions 407084 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@407085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
											 
										 
										
											2014-01-31 23:40:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_BATCHMODE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cdr_submit_batch ( ast_test_flag ( & mod_cfg - > general - > batch_settings . settings ,  BATCH_MODE_SAFE_SHUTDOWN ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-06-03 01:42:31 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  ast_cdr_engine_reload ( void )  
						 
					
						
							
								
									
										
										
										
											2010-07-08 14:48:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  old_mod_cfg ,  ao2_global_obj_ref ( module_configs ) ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RAII_VAR ( struct  module_config  * ,  mod_cfg ,  NULL ,  ao2_cleanup ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-08 14:48:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( process_config ( 1 ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-08 14:48:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									mod_cfg  =  ao2_global_obj_ref ( module_configs ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-08 14:48:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_ENABLED )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											! ( ast_test_flag ( & mod_cfg - > general - > settings ,  CDR_BATCHMODE ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If batch mode used to be enabled, finalize the batch */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ast_test_flag ( & old_mod_cfg - > general - > settings ,  CDR_BATCHMODE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											finalize_batch_mode ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-08 14:48:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-08 14:48:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-10-02 21:26:34 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  cdr_toggle_runtime_options ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-07-08 14:48:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-17 03:00:38 +00:00