1999-12-04 21:35:07 +00:00
/*
2005-09-14 20:46:50 +00:00
* Asterisk -- An open source telephony toolkit.
1999-12-04 21:35:07 +00:00
*
2006-04-10 23:01:22 +00:00
* Copyright (C) 1999 - 2006, Digium, Inc.
1999-12-04 21:35:07 +00:00
*
2004-09-22 05:19:06 +00:00
* Mark Spencer <markster@digium.com>
1999-12-04 21:35:07 +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.
*
1999-12-04 21:35:07 +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
2005-09-14 20:46:50 +00:00
*
2005-10-24 20:12:06 +00:00
* \brief dial() & retrydial() - Trivial application to dial a channel and send an URL on answer
2005-12-30 21:18:06 +00:00
*
* \author Mark Spencer <markster@digium.com>
2008-02-09 11:27:10 +00:00
*
2005-11-06 15:09:47 +00:00
* \ingroup applications
1999-12-04 21:35:07 +00:00
*/
2008-01-22 17:42:27 +00:00
/*** MODULEINFO
<depend>chan_local</depend>
***/
2006-06-07 18:54:56 +00:00
#include "asterisk.h"
ASTERISK_FILE_VERSION ( __FILE__ , "$Revision$" )
2005-06-06 22:39:32 +00:00
#include <sys/time.h>
#include <sys/signal.h>
2006-08-05 06:39:43 +00:00
#include <sys/stat.h>
2005-06-06 22:39:32 +00:00
#include <netinet/in.h>
2008-02-09 11:27:10 +00:00
#include "asterisk/paths.h" /* use ast_config_AST_DATA_DIR */
2005-04-21 06:02:45 +00:00
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/say.h"
#include "asterisk/config.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/causes.h"
2005-12-20 17:52:31 +00:00
#include "asterisk/rtp.h"
2007-11-27 06:47:08 +00:00
#include "asterisk/cdr.h"
2005-04-21 06:02:45 +00:00
#include "asterisk/manager.h"
2005-07-12 03:23:31 +00:00
#include "asterisk/privacy.h"
2006-02-01 23:05:28 +00:00
#include "asterisk/stringfields.h"
2007-12-04 17:08:36 +00:00
#include "asterisk/global_datastores.h"
2008-03-05 16:23:44 +00:00
#include "asterisk/dsp.h"
1999-12-04 21:35:07 +00:00
static char * app = "Dial" ;
2003-11-06 04:08:40 +00:00
static char * synopsis = "Place a call and connect to the current channel" ;
2001-05-07 03:15:48 +00:00
static char * descrip =
2007-07-23 19:51:41 +00:00
" Dial(Technology/resource[&Tech2/resource2...][,timeout][,options][,URL]): \n "
2006-11-16 23:20:52 +00:00
"This application will place calls to one or more specified channels. As soon \n "
2005-11-11 13:34:38 +00:00
"as one of the requested channels answers, the originating channel will be \n "
"answered, if it has not already been answered. These two channels will then \n "
"be active in a bridged call. All other channels that were requested will then \n "
"be hung up. \n "
" Unless there is a timeout specified, the Dial application will wait \n "
"indefinitely until one of the called channels answers, the user hangs up, or \n "
"if all of the called channels are busy or unavailable. Dialplan executing will \n "
2005-11-11 15:52:55 +00:00
"continue if no requested channels can be called, or if the timeout expires. \n\n "
2005-11-11 13:34:38 +00:00
" This application sets the following channel variables upon completion: \n "
" DIALEDTIME - This is the time from dialing a channel until when it \n "
2008-02-09 11:27:10 +00:00
" is disconnected. \n "
2005-11-11 13:34:38 +00:00
" ANSWEREDTIME - This is the amount of time for actual call. \n "
" DIALSTATUS - This is the status of the call: \n "
2008-02-09 11:27:10 +00:00
" CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL \n "
2007-02-03 20:46:36 +00:00
" DONTCALL | TORTURE | INVALIDARGS \n "
2005-11-11 13:34:38 +00:00
" For the Privacy and Screening Modes, the DIALSTATUS variable will be set to \n "
"DONTCALL if the called party chooses to send the calling party to the 'Go Away' \n "
"script. The DIALSTATUS variable will be set to TORTURE if the called party \n "
"wants to send the caller to the 'torture' script. \n "
" This application will report normal termination if the originating channel \n "
"hangs up, or if the call is bridged and either of the parties in the bridge \n "
"ends the call. \n "
2004-07-19 19:47:21 +00:00
" The optional URL will be sent to the called party if the channel supports it. \n "
2004-11-07 21:49:43 +00:00
" If the OUTBOUND_GROUP variable is set, all peer channels created by this \n "
2007-04-13 19:18:46 +00:00
"application will be put into that group (as in Set(GROUP()=...). \n "
" If the OUTBOUND_GROUP_ONCE variable is set, all peer channels created by this \n "
"application will be put into that group (as in Set(GROUP()=...). Unlike OUTBOUND_GROUP, \n "
"however, the variable will be unset after use. \n\n "
2005-11-11 13:34:38 +00:00
" Options: \n "
" A(x) - Play an announcement to the called party, using 'x' as the file. \n "
" C - Reset the CDR for this call. \n "
2007-07-09 08:27:37 +00:00
" c - If DIAL cancels this call, always set the flag to tell the channel \n "
" driver that the call is answered elsewhere. \n "
2005-11-11 13:34:38 +00:00
" d - Allow the calling user to dial a 1 digit extension while waiting for \n "
" a call to be answered. Exit to that extension if it exists in the \n "
" current context, or the context defined in the EXITCONTEXT variable, \n "
" if it exists. \n "
" D([called][:calling]) - Send the specified DTMF strings *after* the called \n "
" party has answered, but before the call gets bridged. The 'called' \n "
" DTMF string is sent to the called party, and the 'calling' DTMF \n "
" string is sent to the calling party. Both parameters can be used \n "
2007-07-17 19:40:29 +00:00
" alone. \n "
" e - execute the 'h' extension for peer after the call ends \n "
2005-11-11 13:34:38 +00:00
" f - Force the callerid of the *calling* channel to be set as the \n "
" extension associated with the channel using a dialplan 'hint'. \n "
" For example, some PSTNs do not allow CallerID to be set to anything \n "
" other than the number assigned to the caller. \n "
" g - Proceed with dialplan execution at the current extension if the \n "
" destination channel hangs up. \n "
2006-03-19 10:11:29 +00:00
" G(context^exten^pri) - If the call is answered, transfer the calling party to \n "
" the specified priority and the called party to the specified priority+1. \n "
" Optionally, an extension, or extension and context may be specified. \n "
2006-05-03 21:11:23 +00:00
" Otherwise, the current extension is used. You cannot use any additional \n "
2008-02-09 11:27:10 +00:00
" action post answer options in conjunction with this option. \n "
2005-11-11 13:34:38 +00:00
" h - Allow the called party to hang up by sending the '*' DTMF digit. \n "
" H - Allow the calling party to hang up by hitting the '*' DTMF digit. \n "
2006-05-31 15:52:32 +00:00
" i - Asterisk will ignore any forwarding requests it may receive on this \n "
" dial attempt. \n "
2007-06-19 23:36:34 +00:00
" k - Allow the called party to enable parking of the call by sending \n "
" the DTMF sequence defined for call parking in features.conf. \n "
" K - Allow the calling party to enable parking of the call by sending \n "
" the DTMF sequence defined for call parking in features.conf. \n "
2005-11-11 13:34:38 +00:00
" L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are \n "
" left. Repeat the warning every 'z' ms. The following special \n "
" variables can be used with this option: \n "
" * LIMIT_PLAYAUDIO_CALLER yes|no (default yes) \n "
" Play sounds to the caller. \n "
" * LIMIT_PLAYAUDIO_CALLEE yes|no \n "
" Play sounds to the callee. \n "
" * LIMIT_TIMEOUT_FILE File to play when time is up. \n "
" * LIMIT_CONNECT_FILE File to play when call begins. \n "
" * LIMIT_WARNING_FILE File to play as warning if 'y' is defined. \n "
" The default is to say the time remaining. \n "
" m([class]) - Provide hold music to the calling party until a requested \n "
" channel answers. A specific MusicOnHold class can be \n "
" specified. \n "
" M(x[^arg]) - Execute the Macro for the *called* channel before connecting \n "
" to the calling channel. Arguments can be specified to the Macro \n "
" using '^' as a delimeter. The Macro can set the variable \n "
2008-02-09 11:27:10 +00:00
" MACRO_RESULT to specify the following actions after the Macro is \n "
2005-11-11 13:34:38 +00:00
" finished executing. \n "
" * ABORT Hangup both legs of the call. \n "
" * CONGESTION Behave as if line congestion was encountered. \n "
2007-06-12 15:58:28 +00:00
" * BUSY Behave as if a busy signal was encountered. \n "
2005-11-11 13:34:38 +00:00
" * CONTINUE Hangup the called party and allow the calling party \n "
" to continue dialplan execution at the next priority. \n "
" * GOTO:<context>^<exten>^<priority> - Transfer the call to the \n "
" specified priority. Optionally, an extension, or \n "
" extension and priority can be specified. \n "
2006-05-03 21:11:23 +00:00
" You cannot use any additional action post answer options in conjunction \n "
2006-09-06 17:14:50 +00:00
" with this option. Also, pbx services are not run on the peer (called) channel, \n "
" so you will not be able to set timeouts via the TIMEOUT() function in this macro. \n "
2005-11-11 13:34:38 +00:00
" n - This option is a modifier for the screen/privacy mode. It specifies \n "
" that no introductions are to be saved in the priv-callerintros \n "
" directory. \n "
" N - This option is a modifier for the screen/privacy mode. It specifies \n "
" that if callerID is present, do not screen the call. \n "
" o - Specify that the CallerID that was present on the *calling* channel \n "
" be set as the CallerID on the *called* channel. This was the \n "
" behavior of Asterisk 1.0 and earlier. \n "
2006-04-22 11:30:06 +00:00
" O([x]) - \" Operator Services \" mode (Zaptel channel to Zaptel channel \n "
" only, if specified on non-Zaptel interface, it will be ignored). \n "
" When the destination answers (presumably an operator services \n "
" station), the originator no longer has control of their line. \n "
" They may hang up, but the switch will not release their line \n "
" until the destination party hangs up (the operator). Specified \n "
" without an arg, or with 1 as an arg, the originator hanging up \n "
" will cause the phone to ring back immediately. With a 2 specified, \n "
" when the \" operator \" flashes the trunk, it will ring their phone \n "
" back. \n "
2005-11-11 13:34:38 +00:00
" p - This option enables screening mode. This is basically Privacy mode \n "
" without memory. \n "
" P([x]) - Enable privacy mode. Use 'x' as the family/key in the database if \n "
" it is provided. The current extension is used if a database \n "
" family/key is not specified. \n "
" r - Indicate ringing to the calling party. Pass no audio to the calling \n "
" party until the called channel has answered. \n "
" S(x) - Hang up the call after 'x' seconds *after* the called party has \n "
2008-02-09 11:27:10 +00:00
" answered the call. \n "
2005-11-11 13:34:38 +00:00
" t - Allow the called party to transfer the calling party by sending the \n "
2006-01-11 03:13:45 +00:00
" DTMF sequence defined in features.conf. \n "
2005-11-11 13:34:38 +00:00
" T - Allow the calling party to transfer the called party by sending the \n "
" DTMF sequence defined in features.conf. \n "
2007-06-19 23:36:34 +00:00
" U(x[^arg]) - Execute via Gosub the routine 'x' for the *called* channel before connecting \n "
" to the calling channel. Arguments can be specified to the Gosub \n "
" using '^' as a delimeter. The Gosub routine can set the variable \n "
2008-02-09 11:27:10 +00:00
" GOSUB_RESULT to specify the following actions after the Gosub returns. \n "
2007-06-19 23:36:34 +00:00
" * ABORT Hangup both legs of the call. \n "
" * CONGESTION Behave as if line congestion was encountered. \n "
2007-06-20 17:35:08 +00:00
" * BUSY Behave as if a busy signal was encountered. \n "
2007-06-19 23:36:34 +00:00
" * CONTINUE Hangup the called party and allow the calling party \n "
" to continue dialplan execution at the next priority. \n "
" * GOTO:<context>^<exten>^<priority> - Transfer the call to the \n "
" specified priority. Optionally, an extension, or \n "
" extension and priority can be specified. \n "
" You cannot use any additional action post answer options in conjunction \n "
" with this option. Also, pbx services are not run on the peer (called) channel, \n "
" so you will not be able to set timeouts via the TIMEOUT() function in this routine. \n "
2005-11-11 13:34:38 +00:00
" w - Allow the called party to enable recording of the call by sending \n "
" the DTMF sequence defined for one-touch recording in features.conf. \n "
" W - Allow the calling party to enable recording of the call by sending \n "
2007-11-30 21:19:57 +00:00
" the DTMF sequence defined for one-touch recording in features.conf. \n "
" x - Allow the called party to enable recording of the call by sending \n "
" the DTMF sequence defined for one-touch automixmonitor in features.conf \n "
" X - Allow the calling party to enable recording of the call by sending \n "
" the DTMF sequence defined for one-touch automixmonitor in features.conf \n " ;
2008-02-09 11:27:10 +00:00
2005-01-18 03:12:53 +00:00
/* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
static char * rapp = "RetryDial" ;
2005-04-27 01:50:53 +00:00
static char * rsynopsis = "Place a call, retrying on failure allowing optional exit extension." ;
2005-01-18 03:12:53 +00:00
static char * rdescrip =
2007-07-23 19:51:41 +00:00
" RetryDial(announce,sleep,retries,dialargs): This application will attempt to \n "
2005-11-11 13:34:38 +00:00
"place a call using the normal Dial application. If no channel can be reached, \n "
2005-11-14 10:24:59 +00:00
"the 'announce' file will be played. Then, it will wait 'sleep' number of \n "
2005-11-11 13:34:38 +00:00
"seconds before retying the call. After 'retires' number of attempts, the \n "
"calling channel will continue at the next priority in the dialplan. If the \n "
"'retries' setting is set to 0, this application will retry endlessly. \n "
" While waiting to retry a call, a 1 digit extension may be dialed. If that \n "
"extension exists in either the context defined in ${EXITCONTEXT} or the current \n "
"one, The call will jump to that extension immediately. \n "
" The 'dialargs' are specified in the same format that arguments are provided \n "
"to the Dial application. \n " ;
2005-01-18 03:12:53 +00:00
2005-11-03 21:40:36 +00:00
enum {
2007-12-12 20:05:13 +00:00
OPT_ANNOUNCE = ( 1 << 0 ),
OPT_RESETCDR = ( 1 << 1 ),
OPT_DTMF_EXIT = ( 1 << 2 ),
OPT_SENDDTMF = ( 1 << 3 ),
OPT_FORCECLID = ( 1 << 4 ),
OPT_GO_ON = ( 1 << 5 ),
OPT_CALLEE_HANGUP = ( 1 << 6 ),
OPT_CALLER_HANGUP = ( 1 << 7 ),
OPT_DURATION_LIMIT = ( 1 << 9 ),
OPT_MUSICBACK = ( 1 << 10 ),
OPT_CALLEE_MACRO = ( 1 << 11 ),
OPT_SCREEN_NOINTRO = ( 1 << 12 ),
OPT_SCREEN_NOCLID = ( 1 << 13 ),
OPT_ORIGINAL_CLID = ( 1 << 14 ),
OPT_SCREENING = ( 1 << 15 ),
OPT_PRIVACY = ( 1 << 16 ),
OPT_RINGBACK = ( 1 << 17 ),
OPT_DURATION_STOP = ( 1 << 18 ),
OPT_CALLEE_TRANSFER = ( 1 << 19 ),
OPT_CALLER_TRANSFER = ( 1 << 20 ),
OPT_CALLEE_MONITOR = ( 1 << 21 ),
OPT_CALLER_MONITOR = ( 1 << 22 ),
OPT_GOTO = ( 1 << 23 ),
OPT_OPERMODE = ( 1 << 24 ),
OPT_CALLEE_PARK = ( 1 << 25 ),
OPT_CALLER_PARK = ( 1 << 26 ),
2006-05-31 15:52:32 +00:00
OPT_IGNORE_FORWARDING = ( 1 << 27 ),
2007-12-12 20:05:13 +00:00
OPT_CALLEE_GOSUB = ( 1 << 28 ),
2007-11-30 21:19:57 +00:00
OPT_CALLEE_MIXMONITOR = ( 1 << 29 ),
OPT_CALLER_MIXMONITOR = ( 1 << 30 ),
2007-04-09 22:49:32 +00:00
};
2005-11-03 21:40:36 +00:00
2008-02-09 11:27:10 +00:00
#define DIAL_STILLGOING (1 << 31)
#define DIAL_NOFORWARDHTML ((uint64_t)1 << 32) /* flags are now 64 bits, so keep it up! */
#define OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 33)
#define OPT_PEER_H ((uint64_t)1 << 34)
2005-11-03 21:40:36 +00:00
enum {
OPT_ARG_ANNOUNCE = 0 ,
OPT_ARG_SENDDTMF ,
OPT_ARG_GOTO ,
OPT_ARG_DURATION_LIMIT ,
OPT_ARG_MUSICBACK ,
OPT_ARG_CALLEE_MACRO ,
2007-06-19 23:36:34 +00:00
OPT_ARG_CALLEE_GOSUB ,
2005-11-03 21:40:36 +00:00
OPT_ARG_PRIVACY ,
OPT_ARG_DURATION_STOP ,
2006-04-22 11:30:06 +00:00
OPT_ARG_OPERMODE ,
2005-11-03 21:40:36 +00:00
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE ,
2007-04-09 22:49:32 +00:00
};
2005-11-03 21:40:36 +00:00
2007-11-14 01:40:47 +00:00
AST_APP_OPTIONS ( dial_exec_options , BEGIN_OPTIONS
2005-11-03 21:40:36 +00:00
AST_APP_OPTION_ARG ( 'A' , OPT_ANNOUNCE , OPT_ARG_ANNOUNCE ),
AST_APP_OPTION ( 'C' , OPT_RESETCDR ),
2007-07-09 08:27:37 +00:00
AST_APP_OPTION ( 'c' , OPT_CANCEL_ELSEWHERE ),
2005-11-03 21:40:36 +00:00
AST_APP_OPTION ( 'd' , OPT_DTMF_EXIT ),
AST_APP_OPTION_ARG ( 'D' , OPT_SENDDTMF , OPT_ARG_SENDDTMF ),
2007-07-17 19:40:29 +00:00
AST_APP_OPTION ( 'e' , OPT_PEER_H ),
2005-11-03 21:40:36 +00:00
AST_APP_OPTION ( 'f' , OPT_FORCECLID ),
AST_APP_OPTION ( 'g' , OPT_GO_ON ),
AST_APP_OPTION_ARG ( 'G' , OPT_GOTO , OPT_ARG_GOTO ),
AST_APP_OPTION ( 'h' , OPT_CALLEE_HANGUP ),
AST_APP_OPTION ( 'H' , OPT_CALLER_HANGUP ),
2006-05-31 15:52:32 +00:00
AST_APP_OPTION ( 'i' , OPT_IGNORE_FORWARDING ),
2007-06-19 23:36:34 +00:00
AST_APP_OPTION ( 'k' , OPT_CALLEE_PARK ),
AST_APP_OPTION ( 'K' , OPT_CALLER_PARK ),
2007-08-31 18:46:02 +00:00
AST_APP_OPTION ( 'k' , OPT_CALLEE_PARK ),
AST_APP_OPTION ( 'K' , OPT_CALLER_PARK ),
2005-11-03 21:40:36 +00:00
AST_APP_OPTION_ARG ( 'L' , OPT_DURATION_LIMIT , OPT_ARG_DURATION_LIMIT ),
AST_APP_OPTION_ARG ( 'm' , OPT_MUSICBACK , OPT_ARG_MUSICBACK ),
AST_APP_OPTION_ARG ( 'M' , OPT_CALLEE_MACRO , OPT_ARG_CALLEE_MACRO ),
AST_APP_OPTION ( 'n' , OPT_SCREEN_NOINTRO ),
AST_APP_OPTION ( 'N' , OPT_SCREEN_NOCLID ),
AST_APP_OPTION ( 'o' , OPT_ORIGINAL_CLID ),
2007-12-12 20:05:13 +00:00
AST_APP_OPTION_ARG ( 'O' , OPT_OPERMODE , OPT_ARG_OPERMODE ),
2005-11-03 21:40:36 +00:00
AST_APP_OPTION ( 'p' , OPT_SCREENING ),
AST_APP_OPTION_ARG ( 'P' , OPT_PRIVACY , OPT_ARG_PRIVACY ),
AST_APP_OPTION ( 'r' , OPT_RINGBACK ),
AST_APP_OPTION_ARG ( 'S' , OPT_DURATION_STOP , OPT_ARG_DURATION_STOP ),
AST_APP_OPTION ( 't' , OPT_CALLEE_TRANSFER ),
AST_APP_OPTION ( 'T' , OPT_CALLER_TRANSFER ),
2007-06-19 23:36:34 +00:00
AST_APP_OPTION_ARG ( 'U' , OPT_CALLEE_GOSUB , OPT_ARG_CALLEE_GOSUB ),
2005-11-03 21:40:36 +00:00
AST_APP_OPTION ( 'w' , OPT_CALLEE_MONITOR ),
AST_APP_OPTION ( 'W' , OPT_CALLER_MONITOR ),
2007-11-30 21:19:57 +00:00
AST_APP_OPTION ( 'x' , OPT_CALLEE_MIXMONITOR ),
AST_APP_OPTION ( 'X' , OPT_CALLER_MIXMONITOR ),
2007-11-14 01:40:47 +00:00
END_OPTIONS );
2005-11-03 21:40:36 +00:00
2007-10-01 14:27:02 +00:00
#define CAN_EARLY_BRIDGE(flags) (!ast_test_flag64(flags, OPT_CALLEE_HANGUP | \
OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \
OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK | OPT_CALLER_PARK))
2007-10-01 13:53:09 +00:00
2006-12-19 16:36:45 +00:00
/*
* The list of active channels
*/
struct chanlist {
struct chanlist * next ;
1999-12-04 21:35:07 +00:00
struct ast_channel * chan ;
2007-07-17 19:40:29 +00:00
uint64_t flags ;
1999-12-04 21:35:07 +00:00
};
2007-07-09 08:27:37 +00:00
static void hanguptree ( struct chanlist * outgoing , struct ast_channel * exception , int answered_elsewhere )
1999-12-04 21:35:07 +00:00
{
/* Hang up a tree of stuff */
2006-12-19 16:36:45 +00:00
struct chanlist * oo ;
2005-01-18 03:12:53 +00:00
while ( outgoing ) {
1999-12-04 21:35:07 +00:00
/* Hangup any existing lines we have open */
2007-07-09 08:27:37 +00:00
if ( outgoing -> chan && ( outgoing -> chan != exception )) {
if ( answered_elsewhere )
ast_set_flag ( outgoing -> chan , AST_FLAG_ANSWERED_ELSEWHERE );
1999-12-04 21:35:07 +00:00
ast_hangup ( outgoing -> chan );
2007-07-09 08:27:37 +00:00
}
1999-12-04 21:35:07 +00:00
oo = outgoing ;
2007-12-12 20:05:13 +00:00
outgoing = outgoing -> next ;
2007-06-06 21:20:11 +00:00
ast_free ( oo );
1999-12-04 21:35:07 +00:00
}
}
2004-06-22 17:42:14 +00:00
#define AST_MAX_WATCHERS 256
2001-05-07 03:15:48 +00:00
2006-11-03 22:36:17 +00:00
/*
* argument to handle_cause() and other functions.
*/
struct cause_args {
struct ast_channel * chan ;
int busy ;
int congestion ;
int nochan ;
};
static void handle_cause ( int cause , struct cause_args * num )
{
struct ast_cdr * cdr = num -> chan -> cdr ;
switch ( cause ) {
case AST_CAUSE_BUSY :
if ( cdr )
ast_cdr_busy ( cdr );
num -> busy ++ ;
break ;
case AST_CAUSE_CONGESTION :
if ( cdr )
ast_cdr_failed ( cdr );
num -> congestion ++ ;
break ;
case AST_CAUSE_UNREGISTERED :
if ( cdr )
ast_cdr_failed ( cdr );
num -> nochan ++ ;
break ;
case AST_CAUSE_NORMAL_CLEARING :
break ;
default :
num -> nochan ++ ;
break ;
}
}
2005-01-18 03:12:53 +00:00
2006-11-03 21:51:16 +00:00
/* free the buffer if allocated, and set the pointer to the second arg */
#define S_REPLACE(s, new_val) \
do { \
if (s) \
2007-12-12 20:05:13 +00:00
ast_free(s); \
2006-11-03 21:51:16 +00:00
s = (new_val); \
} while (0)
2005-01-18 03:12:53 +00:00
2008-02-09 11:27:10 +00:00
static int onedigit_goto ( struct ast_channel * chan , const char * context , char exten , int pri )
2005-01-18 03:12:53 +00:00
{
2005-04-29 15:04:26 +00:00
char rexten [ 2 ] = { exten , '\0' };
2005-01-18 03:12:53 +00:00
if ( context ) {
2005-06-01 18:02:46 +00:00
if ( ! ast_goto_if_exists ( chan , context , rexten , pri ))
2005-01-18 03:12:53 +00:00
return 1 ;
} else {
2005-06-01 18:02:46 +00:00
if ( ! ast_goto_if_exists ( chan , chan -> context , rexten , pri ))
2005-01-18 03:12:53 +00:00
return 1 ;
2005-04-29 15:04:26 +00:00
else if ( ! ast_strlen_zero ( chan -> macrocontext )) {
2005-06-01 18:02:46 +00:00
if ( ! ast_goto_if_exists ( chan , chan -> macrocontext , rexten , pri ))
2005-01-18 03:12:53 +00:00
return 1 ;
}
}
return 0 ;
}
2004-10-26 22:25:43 +00:00
2006-04-19 14:14:40 +00:00
static const char * get_cid_name ( char * name , int namelen , struct ast_channel * chan )
2005-02-01 01:53:25 +00:00
{
2006-04-19 14:14:40 +00:00
const char * context = S_OR ( chan -> macrocontext , chan -> context );
const char * exten = S_OR ( chan -> macroexten , chan -> exten );
2005-02-01 01:53:25 +00:00
2006-04-19 14:14:40 +00:00
return ast_get_hint ( NULL , 0 , name , namelen , chan , context , exten ) ? name : "" ;
2005-02-01 01:53:25 +00:00
}
2007-12-06 15:04:34 +00:00
static void senddialevent ( struct ast_channel * src , struct ast_channel * dst , const char * dialstring )
2005-02-07 15:19:34 +00:00
{
2008-02-09 11:27:10 +00:00
manager_event ( EVENT_FLAG_CALL , "Dial" ,
"SubEvent: Begin \r\n "
"Channel: %s \r\n "
"Destination: %s \r\n "
"CallerIDNum: %s \r\n "
"CallerIDName: %s \r\n "
"UniqueID: %s \r\n "
"DestUniqueID: %s \r\n "
"Dialstring: %s \r\n " ,
src -> name , dst -> name , S_OR ( src -> cid . cid_num , "<unknown>" ),
S_OR ( src -> cid . cid_name , "<unknown>" ), src -> uniqueid ,
dst -> uniqueid , dialstring ? dialstring : "" );
2005-02-07 15:19:34 +00:00
}
2006-10-30 23:11:55 +00:00
static void senddialendevent ( const struct ast_channel * src , const char * dialstatus )
{
manager_event ( EVENT_FLAG_CALL , "Dial" ,
2008-02-09 11:27:10 +00:00
"SubEvent: End \r\n "
"Channel: %s \r\n "
"UniqueID: %s \r\n "
"DialStatus: %s \r\n " ,
src -> name , src -> uniqueid , dialstatus );
}
2006-10-30 23:11:55 +00:00
2006-11-21 11:53:06 +00:00
/*!
* helper function for wait_for_answer()
*
* XXX this code is highly suspicious, as it essentially overwrites
* the outgoing channel without properly deleting it.
*/
2006-12-19 16:36:45 +00:00
static void do_forward ( struct chanlist * o ,
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
struct cause_args * num , struct ast_flags64 * peerflags , int single )
2006-11-04 00:01:40 +00:00
{
char tmpchan [ 256 ];
2007-02-27 22:17:42 +00:00
struct ast_channel * original = o -> chan ;
2006-11-04 00:01:40 +00:00
struct ast_channel * c = o -> chan ; /* the winner */
struct ast_channel * in = num -> chan ; /* the input channel */
char * stuff ;
char * tech ;
int cause ;
ast_copy_string ( tmpchan , c -> call_forward , sizeof ( tmpchan ));
if (( stuff = strchr ( tmpchan , '/' ))) {
* stuff ++ = '\0' ;
tech = tmpchan ;
} else {
const char * forward_context = pbx_builtin_getvar_helper ( c , "FORWARD_CONTEXT" );
snprintf ( tmpchan , sizeof ( tmpchan ), "%s@%s" , c -> call_forward , forward_context ? forward_context : c -> context );
stuff = tmpchan ;
tech = "Local" ;
}
/* Before processing channel, go ahead and check for forwarding */
2007-12-04 17:08:36 +00:00
ast_verb ( 3 , "Now forwarding %s to '%s/%s' (thanks to %s) \n " , in -> name , tech , stuff , c -> name );
/* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
if ( ast_test_flag64 ( peerflags , OPT_IGNORE_FORWARDING )) {
ast_verb ( 3 , "Forwarding %s to '%s/%s' prevented. \n " , in -> name , tech , stuff );
2006-11-04 00:01:40 +00:00
c = o -> chan = NULL ;
2007-12-04 17:08:36 +00:00
cause = AST_CAUSE_BUSY ;
} else {
/* Setup parameters */
c = o -> chan = ast_request ( tech , in -> nativeformats , stuff , & cause );
if ( c ) {
if ( single )
ast_channel_make_compatible ( o -> chan , in );
ast_channel_inherit_variables ( in , o -> chan );
ast_channel_datastore_inherit ( in , o -> chan );
} else
ast_log ( LOG_NOTICE , "Unable to create local channel for call forward to '%s/%s' (cause = %d) \n " , tech , stuff , cause );
2006-11-04 00:01:40 +00:00
}
if ( ! c ) {
2008-02-09 11:27:10 +00:00
ast_clear_flag64 ( o , DIAL_STILLGOING );
2006-11-04 00:01:40 +00:00
handle_cause ( cause , num );
} else {
char * new_cid_num , * new_cid_name ;
struct ast_channel * src ;
ast_rtp_make_compatible ( c , in , single );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( o , OPT_FORCECLID )) {
2006-11-04 00:01:40 +00:00
new_cid_num = ast_strdup ( S_OR ( in -> macroexten , in -> exten ));
new_cid_name = NULL ; /* XXX no name ? */
2008-02-09 11:27:10 +00:00
src = c ; /* XXX possible bug in previous code, which used 'winner' ? it may have changed */
2006-11-04 00:01:40 +00:00
} else {
new_cid_num = ast_strdup ( in -> cid . cid_num );
new_cid_name = ast_strdup ( in -> cid . cid_name );
src = in ;
}
ast_string_field_set ( c , accountcode , src -> accountcode );
c -> cdrflags = src -> cdrflags ;
S_REPLACE ( c -> cid . cid_num , new_cid_num );
S_REPLACE ( c -> cid . cid_name , new_cid_name );
if ( in -> cid . cid_ani ) { /* XXX or maybe unconditional ? */
S_REPLACE ( c -> cid . cid_ani , ast_strdup ( in -> cid . cid_ani ));
}
S_REPLACE ( c -> cid . cid_rdnis , ast_strdup ( S_OR ( in -> macroexten , in -> exten )));
if ( ast_call ( c , tmpchan , 0 )) {
ast_log ( LOG_NOTICE , "Failed to dial on local channel for call forward to '%s' \n " , tmpchan );
2008-02-09 11:27:10 +00:00
ast_clear_flag64 ( o , DIAL_STILLGOING );
2007-02-27 22:17:42 +00:00
ast_hangup ( original );
2006-11-04 00:01:40 +00:00
c = o -> chan = NULL ;
num -> nochan ++ ;
} else {
2007-12-06 15:04:34 +00:00
senddialevent ( in , c , stuff );
2006-11-04 00:01:40 +00:00
/* After calling, set callerid to extension */
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ! ast_test_flag64 ( peerflags , OPT_ORIGINAL_CLID )) {
2007-06-04 18:00:24 +00:00
char cidname [ AST_MAX_EXTENSION ] = "" ;
2006-11-04 00:01:40 +00:00
ast_set_callerid ( c , S_OR ( in -> macroexten , in -> exten ), get_cid_name ( cidname , sizeof ( cidname ), in ), NULL );
}
2006-11-21 11:53:06 +00:00
/* Hangup the original channel now, in case we needed it */
2007-02-27 22:17:42 +00:00
ast_hangup ( original );
2006-11-04 00:01:40 +00:00
}
}
}
2006-11-04 11:00:49 +00:00
/* argument used for some functions. */
struct privacy_args {
2008-02-09 11:27:10 +00:00
int sentringing ;
int privdb_val ;
char privcid [ 256 ];
char privintro [ 1024 ];
char status [ 256 ];
2006-11-04 11:00:49 +00:00
};
static struct ast_channel * wait_for_answer ( struct ast_channel * in ,
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
struct chanlist * outgoing , int * to , struct ast_flags64 * peerflags ,
2006-11-04 11:00:49 +00:00
struct privacy_args * pa ,
2007-06-12 15:58:28 +00:00
const struct cause_args * num_in , int * result )
1999-12-04 21:35:07 +00:00
{
2006-11-03 22:36:17 +00:00
struct cause_args num = * num_in ;
int prestart = num . busy + num . congestion + num . nochan ;
1999-12-04 21:35:07 +00:00
int orig = * to ;
struct ast_channel * peer = NULL ;
2006-04-19 16:10:11 +00:00
/* single is set if only one destination is enabled */
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
int single = outgoing && ! outgoing -> next && ! ast_test_flag64 ( outgoing , OPT_MUSICBACK | OPT_RINGBACK );
2007-08-08 21:44:58 +00:00
#ifdef HAVE_EPOLL
struct chanlist * epollo ;
#endif
2008-02-09 11:27:10 +00:00
2001-05-07 03:15:48 +00:00
if ( single ) {
2003-11-05 20:53:49 +00:00
/* Turn off hold music, etc */
2004-07-07 16:02:13 +00:00
ast_deactivate_generator ( in );
2001-05-07 03:15:48 +00:00
/* If we are calling a single channel, make them compatible for in-band tone purpose */
ast_channel_make_compatible ( outgoing -> chan , in );
}
2007-08-08 21:44:58 +00:00
#ifdef HAVE_EPOLL
for ( epollo = outgoing ; epollo ; epollo = epollo -> next )
ast_poll_channel_add ( in , epollo -> chan );
2008-02-09 11:27:10 +00:00
#endif
2005-01-18 03:12:53 +00:00
while ( * to && ! peer ) {
2006-12-19 16:36:45 +00:00
struct chanlist * o ;
2008-02-09 11:27:10 +00:00
int pos = 0 ; /* how many channels do we handle */
2006-04-19 14:02:49 +00:00
int numlines = prestart ;
2006-04-19 16:10:11 +00:00
struct ast_channel * winner ;
struct ast_channel * watchers [ AST_MAX_WATCHERS ];
2006-04-19 14:02:49 +00:00
watchers [ pos ++ ] = in ;
for ( o = outgoing ; o ; o = o -> next ) {
2001-05-07 03:15:48 +00:00
/* Keep track of important channels */
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( o , DIAL_STILLGOING ) && o -> chan )
2001-05-07 03:15:48 +00:00
watchers [ pos ++ ] = o -> chan ;
numlines ++ ;
1999-12-04 21:35:07 +00:00
}
2008-02-09 11:27:10 +00:00
if ( pos == 1 ) { /* only the input channel is available */
2006-11-03 22:36:17 +00:00
if ( numlines == ( num . busy + num . congestion + num . nochan )) {
2007-07-26 15:49:18 +00:00
ast_verb ( 2 , "Everyone is busy/congested at this time (%d:%d/%d/%d) \n " , numlines , num . busy , num . congestion , num . nochan );
2006-11-03 22:36:17 +00:00
if ( num . busy )
2008-02-09 11:27:10 +00:00
strcpy ( pa -> status , "BUSY" );
2006-11-03 22:36:17 +00:00
else if ( num . congestion )
2006-11-04 11:00:49 +00:00
strcpy ( pa -> status , "CONGESTION" );
2006-11-03 22:36:17 +00:00
else if ( num . nochan )
2006-11-04 11:00:49 +00:00
strcpy ( pa -> status , "CHANUNAVAIL" );
1999-12-04 21:35:07 +00:00
} else {
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "No one is available to answer at this time (%d:%d/%d/%d) \n " , numlines , num . busy , num . congestion , num . nochan );
1999-12-04 21:35:07 +00:00
}
2001-05-07 03:15:48 +00:00
* to = 0 ;
1999-12-04 21:35:07 +00:00
return NULL ;
}
2001-05-07 03:15:48 +00:00
winner = ast_waitfor_n ( watchers , pos , to );
2006-04-19 14:02:49 +00:00
for ( o = outgoing ; o ; o = o -> next ) {
struct ast_frame * f ;
struct ast_channel * c = o -> chan ;
if ( c == NULL )
continue ;
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( o , DIAL_STILLGOING ) && c -> _state == AST_STATE_UP ) {
2002-09-02 15:20:28 +00:00
if ( ! peer ) {
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s answered %s \n " , c -> name , in -> name );
2006-04-19 14:02:49 +00:00
peer = c ;
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_copy_flags64 ( peerflags , o ,
2008-02-09 11:27:10 +00:00
OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
OPT_CALLEE_PARK | OPT_CALLER_PARK |
OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
DIAL_NOFORWARDHTML );
2006-11-20 15:55:58 +00:00
ast_copy_string ( c -> dialcontext , "" , sizeof ( c -> dialcontext ));
2006-10-13 21:20:18 +00:00
ast_copy_string ( c -> exten , "" , sizeof ( c -> exten ));
2002-09-02 15:20:28 +00:00
}
2006-04-19 14:02:49 +00:00
continue ;
}
if ( c != winner )
continue ;
2006-11-04 00:01:40 +00:00
/* here, o->chan == c == winner */
2006-04-19 14:02:49 +00:00
if ( ! ast_strlen_zero ( c -> call_forward )) {
2006-11-04 00:01:40 +00:00
do_forward ( o , & num , peerflags , single );
2006-04-19 14:53:18 +00:00
continue ;
2006-04-19 14:02:49 +00:00
}
f = ast_read ( winner );
if ( ! f ) {
2006-04-19 14:53:18 +00:00
in -> hangupcause = c -> hangupcause ;
2007-12-03 14:14:43 +00:00
#ifdef HAVE_EPOLL
ast_poll_channel_del ( in , c );
#endif
2006-04-19 14:53:18 +00:00
ast_hangup ( c );
c = o -> chan = NULL ;
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_clear_flag64 ( o , DIAL_STILLGOING );
2006-11-03 22:36:17 +00:00
handle_cause ( in -> hangupcause , & num );
2006-04-19 14:53:18 +00:00
continue ;
}
if ( f -> frametype == AST_FRAME_CONTROL ) {
switch ( f -> subclass ) {
case AST_CONTROL_ANSWER :
/* This is our guy if someone answered. */
if ( ! peer ) {
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s answered %s \n " , c -> name , in -> name );
2006-04-19 14:53:18 +00:00
peer = c ;
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_copy_flags64 ( peerflags , o ,
2008-02-09 11:27:10 +00:00
OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
OPT_CALLEE_PARK | OPT_CALLER_PARK |
OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
DIAL_NOFORWARDHTML );
2006-11-20 15:55:58 +00:00
ast_copy_string ( c -> dialcontext , "" , sizeof ( c -> dialcontext ));
2006-10-13 21:20:18 +00:00
ast_copy_string ( c -> exten , "" , sizeof ( c -> exten ));
2007-10-01 13:53:09 +00:00
if ( CAN_EARLY_BRIDGE ( peerflags ))
/* Setup early bridge if appropriate */
ast_channel_early_bridge ( in , peer );
2006-04-19 14:53:18 +00:00
}
/* If call has been answered, then the eventual hangup is likely to be normal hangup */
in -> hangupcause = AST_CAUSE_NORMAL_CLEARING ;
c -> hangupcause = AST_CAUSE_NORMAL_CLEARING ;
break ;
case AST_CONTROL_BUSY :
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s is busy \n " , c -> name );
2006-04-19 14:53:18 +00:00
in -> hangupcause = c -> hangupcause ;
ast_hangup ( c );
c = o -> chan = NULL ;
2008-02-09 11:27:10 +00:00
ast_clear_flag64 ( o , DIAL_STILLGOING );
2006-11-03 22:36:17 +00:00
handle_cause ( AST_CAUSE_BUSY , & num );
2006-04-19 14:53:18 +00:00
break ;
case AST_CONTROL_CONGESTION :
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s is circuit-busy \n " , c -> name );
2006-04-19 14:50:17 +00:00
in -> hangupcause = c -> hangupcause ;
ast_hangup ( c );
c = o -> chan = NULL ;
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_clear_flag64 ( o , DIAL_STILLGOING );
2006-11-03 22:36:17 +00:00
handle_cause ( AST_CAUSE_CONGESTION , & num );
2006-04-19 14:53:18 +00:00
break ;
case AST_CONTROL_RINGING :
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s is ringing \n " , c -> name );
2006-05-09 11:44:50 +00:00
/* Setup early media if appropriate */
2007-10-01 13:53:09 +00:00
if ( single && CAN_EARLY_BRIDGE ( peerflags ))
2006-09-21 19:27:26 +00:00
ast_channel_early_bridge ( in , c );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ! ( pa -> sentringing ) && ! ast_test_flag64 ( outgoing , OPT_MUSICBACK )) {
2006-04-19 14:53:18 +00:00
ast_indicate ( in , AST_CONTROL_RINGING );
2006-11-04 11:00:49 +00:00
pa -> sentringing ++ ;
2006-04-19 14:53:18 +00:00
}
break ;
case AST_CONTROL_PROGRESS :
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s is making progress passing it to %s \n " , c -> name , in -> name );
2006-05-09 11:44:50 +00:00
/* Setup early media if appropriate */
2007-10-01 13:53:09 +00:00
if ( single && CAN_EARLY_BRIDGE ( peerflags ))
2006-09-21 19:27:26 +00:00
ast_channel_early_bridge ( in , c );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ! ast_test_flag64 ( outgoing , OPT_RINGBACK ))
2006-04-19 14:53:18 +00:00
ast_indicate ( in , AST_CONTROL_PROGRESS );
break ;
case AST_CONTROL_VIDUPDATE :
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s requested a video update, passing it to %s \n " , c -> name , in -> name );
2006-04-19 14:53:18 +00:00
ast_indicate ( in , AST_CONTROL_VIDUPDATE );
break ;
2008-03-05 22:43:22 +00:00
case AST_CONTROL_SRCUPDATE :
ast_verb ( 3 , "%s requested a source update, passing it to %s \n " , c -> name , in -> name );
ast_indicate ( in , AST_CONTROL_SRCUPDATE );
break ;
2006-04-19 14:53:18 +00:00
case AST_CONTROL_PROCEEDING :
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s is proceeding passing it to %s \n " , c -> name , in -> name );
2007-10-01 13:53:09 +00:00
if ( single && CAN_EARLY_BRIDGE ( peerflags ))
2006-09-21 19:27:26 +00:00
ast_channel_early_bridge ( in , c );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ! ast_test_flag64 ( outgoing , OPT_RINGBACK ))
2006-04-19 14:53:18 +00:00
ast_indicate ( in , AST_CONTROL_PROCEEDING );
break ;
case AST_CONTROL_HOLD :
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "Call on %s placed on hold \n " , c -> name );
2006-04-19 14:53:18 +00:00
ast_indicate ( in , AST_CONTROL_HOLD );
break ;
case AST_CONTROL_UNHOLD :
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "Call on %s left from hold \n " , c -> name );
2006-04-19 14:53:18 +00:00
ast_indicate ( in , AST_CONTROL_UNHOLD );
break ;
case AST_CONTROL_OFFHOOK :
case AST_CONTROL_FLASH :
/* Ignore going off hook and flash */
break ;
case - 1 :
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ! ast_test_flag64 ( outgoing , OPT_RINGBACK | OPT_MUSICBACK )) {
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s stopped sounds \n " , c -> name );
2006-04-19 14:53:18 +00:00
ast_indicate ( in , - 1 );
2006-11-04 11:00:49 +00:00
pa -> sentringing = 0 ;
2006-04-19 14:53:18 +00:00
}
break ;
default :
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , "Dunno what to do with control type %d \n " , f -> subclass );
2006-04-19 14:53:18 +00:00
}
2006-04-19 15:15:03 +00:00
} else if ( single ) {
2008-03-11 15:59:32 +00:00
switch ( f -> frametype ) {
case AST_FRAME_VOICE :
case AST_FRAME_IMAGE :
case AST_FRAME_TEXT :
if ( ast_write ( in , f )) {
ast_log ( LOG_WARNING , "Unable to write frame \n " );
}
break ;
case AST_FRAME_HTML :
if ( ! ast_test_flag64 ( outgoing , DIAL_NOFORWARDHTML ) && ast_channel_sendhtml ( in , f -> subclass , f -> data , f -> datalen ) == - 1 ) {
ast_log ( LOG_WARNING , "Unable to send URL \n " );
}
break ;
default :
break ;
2006-04-19 15:15:03 +00:00
}
1999-12-04 21:35:07 +00:00
}
2006-04-19 14:02:49 +00:00
ast_frfree ( f );
} /* end for */
2001-05-07 03:15:48 +00:00
if ( winner == in ) {
2006-04-19 14:02:49 +00:00
struct ast_frame * f = ast_read ( in );
1999-12-04 21:35:07 +00:00
#if 0
if (f && (f->frametype != AST_FRAME_VOICE))
2005-09-07 19:13:00 +00:00
printf("Frame type: %d, %d\n", f->frametype, f->subclass);
2001-10-15 17:39:25 +00:00
else if (!f || (f->frametype != AST_FRAME_VOICE))
printf("Hangup received on %s\n", in->name);
1999-12-04 21:35:07 +00:00
#endif
2001-10-15 17:39:25 +00:00
if ( ! f || (( f -> frametype == AST_FRAME_CONTROL ) && ( f -> subclass == AST_CONTROL_HANGUP ))) {
1999-12-04 21:35:07 +00:00
/* Got hung up */
2006-01-17 18:54:56 +00:00
* to = - 1 ;
2006-11-04 11:00:49 +00:00
strcpy ( pa -> status , "CANCEL" );
2007-05-18 22:33:51 +00:00
ast_cdr_noanswer ( in -> cdr );
2004-12-06 17:12:21 +00:00
if ( f )
ast_frfree ( f );
1999-12-04 21:35:07 +00:00
return NULL ;
}
2005-01-18 03:12:53 +00:00
2006-11-03 22:01:34 +00:00
/* now f is guaranteed non-NULL */
if ( f -> frametype == AST_FRAME_DTMF ) {
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( peerflags , OPT_DTMF_EXIT )) {
2006-04-19 16:10:11 +00:00
const char * context = pbx_builtin_getvar_helper ( in , "EXITCONTEXT" );
2005-04-29 15:04:26 +00:00
if ( onedigit_goto ( in , context , ( char ) f -> subclass , 1 )) {
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "User hit %c to disconnect call. \n " , f -> subclass );
2007-12-12 20:05:13 +00:00
* to = 0 ;
2007-05-18 22:33:51 +00:00
ast_cdr_noanswer ( in -> cdr );
2005-01-18 03:12:53 +00:00
* result = f -> subclass ;
2006-11-04 11:00:49 +00:00
strcpy ( pa -> status , "CANCEL" );
2005-01-18 03:12:53 +00:00
ast_frfree ( f );
return NULL ;
}
}
2008-02-09 11:27:10 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLER_HANGUP ) &&
( f -> subclass == '*' )) { /* hmm it it not guaranteed to be '*' anymore. */
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "User hit %c to disconnect call. \n " , f -> subclass );
2007-12-12 20:05:13 +00:00
* to = 0 ;
2006-11-04 11:00:49 +00:00
strcpy ( pa -> status , "CANCEL" );
2007-05-18 22:33:51 +00:00
ast_cdr_noanswer ( in -> cdr );
2005-01-18 03:12:53 +00:00
ast_frfree ( f );
return NULL ;
}
2002-09-02 15:20:28 +00:00
}
2005-01-18 03:12:53 +00:00
2005-02-28 06:06:42 +00:00
/* Forward HTML stuff */
2008-02-09 11:27:10 +00:00
if ( single && ( f -> frametype == AST_FRAME_HTML ) && ! ast_test_flag64 ( outgoing , DIAL_NOFORWARDHTML ))
2007-12-12 20:05:13 +00:00
if ( ast_channel_sendhtml ( outgoing -> chan , f -> subclass , f -> data , f -> datalen ) == - 1 )
2006-01-17 18:54:56 +00:00
ast_log ( LOG_WARNING , "Unable to send URL \n " );
2005-02-28 06:06:42 +00:00
2007-02-14 21:10:53 +00:00
if ( single && (( f -> frametype == AST_FRAME_VOICE ) || ( f -> frametype == AST_FRAME_DTMF_BEGIN ) || ( f -> frametype == AST_FRAME_DTMF_END ))) {
2002-09-02 15:20:28 +00:00
if ( ast_write ( outgoing -> chan , f ))
2007-02-14 21:10:53 +00:00
ast_log ( LOG_WARNING , "Unable to forward voice or dtmf \n " );
2002-09-02 15:20:28 +00:00
}
2008-02-09 11:27:10 +00:00
if ( single && ( f -> frametype == AST_FRAME_CONTROL ) &&
(( f -> subclass == AST_CONTROL_HOLD ) ||
( f -> subclass == AST_CONTROL_UNHOLD ) ||
2008-03-05 22:43:22 +00:00
( f -> subclass == AST_CONTROL_VIDUPDATE ) ||
( f -> subclass == AST_CONTROL_SRCUPDATE ))) {
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "%s requested special control %d, passing it to %s \n " , in -> name , f -> subclass , outgoing -> chan -> name );
2006-07-08 02:24:07 +00:00
ast_indicate_data ( outgoing -> chan , f -> subclass , f -> data , f -> datalen );
2005-08-30 02:12:09 +00:00
}
2005-08-03 20:17:53 +00:00
ast_frfree ( f );
1999-12-04 21:35:07 +00:00
}
2007-07-26 15:49:18 +00:00
if ( !* to )
ast_verb ( 3 , "Nobody picked up in %d ms \n " , orig );
2008-02-09 11:27:10 +00:00
if ( !* to || ast_check_hangup ( in ))
2007-05-18 22:33:51 +00:00
ast_cdr_noanswer ( in -> cdr );
1999-12-04 21:35:07 +00:00
}
2008-02-09 11:27:10 +00:00
2007-08-08 21:44:58 +00:00
#ifdef HAVE_EPOLL
2007-12-03 14:14:43 +00:00
for ( epollo = outgoing ; epollo ; epollo = epollo -> next ) {
if ( epollo -> chan )
ast_poll_channel_del ( in , epollo -> chan );
}
2007-08-08 21:44:58 +00:00
#endif
1999-12-04 21:35:07 +00:00
return peer ;
2006-04-19 14:02:49 +00:00
}
static void replace_macro_delimiter ( char * s )
{
for (; * s ; s ++ )
if ( * s == '^' )
2007-07-23 19:51:41 +00:00
* s = ',' ;
1999-12-04 21:35:07 +00:00
}
2006-04-19 17:58:07 +00:00
/* returns true if there is a valid privacy reply */
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
static int valid_priv_reply ( struct ast_flags64 * opts , int res )
2006-04-19 17:58:07 +00:00
{
if ( res < '1' )
return 0 ;
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( opts , OPT_PRIVACY ) && res <= '5' )
2006-04-19 17:58:07 +00:00
return 1 ;
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( opts , OPT_SCREENING ) && res <= '4' )
2006-04-19 17:58:07 +00:00
return 1 ;
return 0 ;
}
2006-11-04 00:50:18 +00:00
static int do_timelimit ( struct ast_channel * chan , struct ast_bridge_config * config ,
char * parse , unsigned int * calldurationlimit )
{
2006-11-14 20:09:10 +00:00
char * stringp = ast_strdupa ( parse );
2006-11-04 00:50:18 +00:00
char * limit_str , * warning_str , * warnfreq_str ;
const char * var ;
2007-12-12 20:05:13 +00:00
int play_to_caller = 0 , play_to_callee = 0 ;
2006-11-04 00:50:18 +00:00
int delta ;
2006-11-14 20:09:10 +00:00
limit_str = strsep ( & stringp , ":" );
warning_str = strsep ( & stringp , ":" );
warnfreq_str = strsep ( & stringp , ":" );
2006-11-04 00:50:18 +00:00
config -> timelimit = atol ( limit_str );
if ( warning_str )
config -> play_warning = atol ( warning_str );
if ( warnfreq_str )
config -> warning_freq = atol ( warnfreq_str );
if ( ! config -> timelimit ) {
ast_log ( LOG_WARNING , "Dial does not accept L(%s), hanging up. \n " , limit_str );
config -> timelimit = config -> play_warning = config -> warning_freq = 0 ;
config -> warning_sound = NULL ;
2008-02-09 11:27:10 +00:00
return - 1 ; /* error */
2006-11-04 00:50:18 +00:00
} else if ( ( delta = config -> play_warning - config -> timelimit ) > 0 ) {
int w = config -> warning_freq ;
/* If the first warning is requested _after_ the entire call would end,
and no warning frequency is requested, then turn off the warning. If
a warning frequency is requested, reduce the 'first warning' time by
that frequency until it falls within the call's total time limit.
Graphically:
timelim->| delta |<-playwarning
0__________________|_________________|
| w | | | |
so the number of intervals to cut is 1+(delta-1)/w
*/
if ( w == 0 ) {
config -> play_warning = 0 ;
} else {
config -> play_warning -= w * ( 1 + ( delta - 1 ) / w );
if ( config -> play_warning < 1 )
config -> play_warning = config -> warning_freq = 0 ;
}
}
2007-12-12 20:05:13 +00:00
var = pbx_builtin_getvar_helper ( chan , "LIMIT_PLAYAUDIO_CALLER" );
2006-11-04 00:50:18 +00:00
play_to_caller = var ? ast_true ( var ) : 1 ;
2008-02-09 11:27:10 +00:00
2007-12-12 20:05:13 +00:00
var = pbx_builtin_getvar_helper ( chan , "LIMIT_PLAYAUDIO_CALLEE" );
2006-11-04 00:50:18 +00:00
play_to_callee = var ? ast_true ( var ) : 0 ;
2008-02-09 11:27:10 +00:00
2006-11-04 00:50:18 +00:00
if ( ! play_to_caller && ! play_to_callee )
play_to_caller = 1 ;
2008-02-09 11:27:10 +00:00
2007-12-12 20:05:13 +00:00
var = pbx_builtin_getvar_helper ( chan , "LIMIT_WARNING_FILE" );
2006-11-04 00:50:18 +00:00
config -> warning_sound = S_OR ( var , "timeleft" );
/* The code looking at config wants a NULL, not just "", to decide
* that the message should not be played, so we replace "" with NULL.
* Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
* not found.
*/
2007-12-12 20:05:13 +00:00
var = pbx_builtin_getvar_helper ( chan , "LIMIT_TIMEOUT_FILE" );
2006-11-04 00:50:18 +00:00
config -> end_sound = S_OR ( var , NULL );
2007-12-12 20:05:13 +00:00
var = pbx_builtin_getvar_helper ( chan , "LIMIT_CONNECT_FILE" );
2006-11-04 00:50:18 +00:00
config -> start_sound = S_OR ( var , NULL );
/* undo effect of S(x) in case they are both used */
* calldurationlimit = 0 ;
/* more efficient to do it like S(x) does since no advanced opts */
if ( ! config -> play_warning && ! config -> start_sound && ! config -> end_sound && config -> timelimit ) {
* calldurationlimit = config -> timelimit / 1000 ;
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "Setting call duration limit to %d seconds. \n " ,
2008-02-09 11:27:10 +00:00
* calldurationlimit );
2006-11-04 00:50:18 +00:00
config -> timelimit = play_to_caller = play_to_callee =
config -> play_warning = config -> warning_freq = 0 ;
2007-07-26 15:49:18 +00:00
} else {
ast_verb ( 3 , "Limit Data for this call: \n " );
ast_verb ( 4 , "timelimit = %ld \n " , config -> timelimit );
ast_verb ( 4 , "play_warning = %ld \n " , config -> play_warning );
ast_verb ( 4 , "play_to_caller = %s \n " , play_to_caller ? "yes" : "no" );
ast_verb ( 4 , "play_to_callee = %s \n " , play_to_callee ? "yes" : "no" );
ast_verb ( 4 , "warning_freq = %ld \n " , config -> warning_freq );
ast_verb ( 4 , "start_sound = %s \n " , S_OR ( config -> start_sound , "" ));
ast_verb ( 4 , "warning_sound = %s \n " , config -> warning_sound );
ast_verb ( 4 , "end_sound = %s \n " , S_OR ( config -> end_sound , "" ));
2006-11-04 00:50:18 +00:00
}
2008-02-09 11:27:10 +00:00
if ( play_to_caller )
ast_set_flag ( & ( config -> features_caller ), AST_FEATURE_PLAY_WARNING );
if ( play_to_callee )
ast_set_flag ( & ( config -> features_callee ), AST_FEATURE_PLAY_WARNING );
2006-11-04 00:50:18 +00:00
return 0 ;
}
2006-11-04 11:00:49 +00:00
static int do_privacy ( struct ast_channel * chan , struct ast_channel * peer ,
2008-02-09 11:27:10 +00:00
struct ast_flags64 * opts , char ** opt_args , struct privacy_args * pa )
2006-11-04 11:00:49 +00:00
{
int res2 ;
int loopcount = 0 ;
2008-02-09 11:27:10 +00:00
/* Get the user's intro, store it in priv-callerintros/$CID,
unless it is already there-- this should be done before the
2006-11-04 11:00:49 +00:00
call is actually dialed */
2008-02-09 11:27:10 +00:00
/* all ring indications and moh for the caller has been halted as soon as the
2006-11-04 11:00:49 +00:00
target extension was picked up. We are going to have to kill some
time and make the caller believe the peer hasn't picked up yet */
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( opts , OPT_MUSICBACK ) && ! ast_strlen_zero ( opt_args [ OPT_ARG_MUSICBACK ])) {
2007-02-09 19:39:26 +00:00
char * original_moh = ast_strdupa ( chan -> musicclass );
2006-11-04 11:00:49 +00:00
ast_indicate ( chan , - 1 );
2007-02-09 19:39:26 +00:00
ast_string_field_set ( chan , musicclass , opt_args [ OPT_ARG_MUSICBACK ]);
2006-11-04 11:00:49 +00:00
ast_moh_start ( chan , opt_args [ OPT_ARG_MUSICBACK ], NULL );
2007-02-09 19:39:26 +00:00
ast_string_field_set ( chan , musicclass , original_moh );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
} else if ( ast_test_flag64 ( opts , OPT_RINGBACK )) {
2006-11-04 11:00:49 +00:00
ast_indicate ( chan , AST_CONTROL_RINGING );
pa -> sentringing ++ ;
}
/* Start autoservice on the other chan ?? */
res2 = ast_autoservice_start ( chan );
/* Now Stream the File */
for ( loopcount = 0 ; loopcount < 3 ; loopcount ++ ) {
2008-02-09 11:27:10 +00:00
if ( res2 && loopcount == 0 ) /* error in ast_autoservice_start() */
2006-11-04 11:00:49 +00:00
break ;
2008-02-09 11:27:10 +00:00
if ( ! res2 ) /* on timeout, play the message again */
2007-12-12 20:05:13 +00:00
res2 = ast_play_and_wait ( peer , "priv-callpending" );
2006-11-04 11:00:49 +00:00
if ( ! valid_priv_reply ( opts , res2 ))
res2 = 0 ;
2008-02-09 11:27:10 +00:00
/* priv-callpending script:
2006-11-04 11:00:49 +00:00
"I have a caller waiting, who introduces themselves as:"
*/
if ( ! res2 )
res2 = ast_play_and_wait ( peer , pa -> privintro );
if ( ! valid_priv_reply ( opts , res2 ))
res2 = 0 ;
/* now get input from the called party, as to their choice */
2007-12-12 20:05:13 +00:00
if ( ! res2 ) {
2006-11-04 11:00:49 +00:00
/* XXX can we have both, or they are mutually exclusive ? */
2007-12-12 20:05:13 +00:00
if ( ast_test_flag64 ( opts , OPT_PRIVACY ))
res2 = ast_play_and_wait ( peer , "priv-callee-options" );
if ( ast_test_flag64 ( opts , OPT_SCREENING ))
res2 = ast_play_and_wait ( peer , "screen-callee-options" );
2006-11-04 11:00:49 +00:00
}
/*! \page DialPrivacy Dial Privacy scripts
\par priv-callee-options script:
"Dial 1 if you wish this caller to reach you directly in the future,
and immediately connect to their incoming call
2008-02-09 11:27:10 +00:00
Dial 2 if you wish to send this caller to voicemail now and
2006-11-04 11:00:49 +00:00
forevermore.
Dial 3 to send this caller to the torture menus, now and forevermore.
Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
Dial 5 to allow this caller to come straight thru to you in the future,
but right now, just this once, send them to voicemail."
\par screen-callee-options script:
"Dial 1 if you wish to immediately connect to the incoming call
Dial 2 if you wish to send this caller to voicemail.
Dial 3 to send this caller to the torture menus.
Dial 4 to send this caller to a simple "go away" menu.
*/
if ( valid_priv_reply ( opts , res2 ))
break ;
/* invalid option */
res2 = ast_play_and_wait ( peer , "vm-sorry" );
}
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( opts , OPT_MUSICBACK )) {
2006-11-04 11:00:49 +00:00
ast_moh_stop ( chan );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
} else if ( ast_test_flag64 ( opts , OPT_RINGBACK )) {
2006-11-04 11:00:49 +00:00
ast_indicate ( chan , - 1 );
2007-12-12 20:05:13 +00:00
pa -> sentringing = 0 ;
2006-11-04 11:00:49 +00:00
}
ast_autoservice_stop ( chan );
2007-12-12 20:05:13 +00:00
if ( ast_test_flag64 ( opts , OPT_PRIVACY ) && ( res2 >= '1' && res2 <= '5' )) {
2006-11-04 11:00:49 +00:00
/* map keypresses to various things, the index is res2 - '1' */
static const char * _val [] = { "ALLOW" , "DENY" , "TORTURE" , "KILL" , "ALLOW" };
static const int _flag [] = { AST_PRIVACY_ALLOW , AST_PRIVACY_DENY , AST_PRIVACY_TORTURE , AST_PRIVACY_KILL , AST_PRIVACY_ALLOW };
int i = res2 - '1' ;
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "--Set privacy database entry %s/%s to %s \n " ,
2008-02-09 11:27:10 +00:00
opt_args [ OPT_ARG_PRIVACY ], pa -> privcid , _val [ i ]);
2006-11-04 11:00:49 +00:00
ast_privacy_set ( opt_args [ OPT_ARG_PRIVACY ], pa -> privcid , _flag [ i ]);
}
switch ( res2 ) {
case '1' :
break ;
case '2' :
ast_copy_string ( pa -> status , "NOANSWER" , sizeof ( pa -> status ));
break ;
case '3' :
ast_copy_string ( pa -> status , "TORTURE" , sizeof ( pa -> status ));
break ;
case '4' :
ast_copy_string ( pa -> status , "DONTCALL" , sizeof ( pa -> status ));
break ;
case '5' :
/* XXX should we set status to DENY ? */
2007-12-12 20:05:13 +00:00
if ( ast_test_flag64 ( opts , OPT_PRIVACY ))
2006-11-04 11:00:49 +00:00
break ;
/* if not privacy, then 5 is the same as "default" case */
2008-02-09 11:27:10 +00:00
default : /* bad input or -1 if failure to start autoservice */
2006-11-04 11:00:49 +00:00
/* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do? */
/* well, there seems basically two choices. Just patch the caller thru immediately,
or,... put 'em thru to voicemail. */
/* since the callee may have hung up, let's do the voicemail thing, no database decision */
ast_log ( LOG_NOTICE , "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding \n " );
/* XXX should we set status to DENY ? */
/* XXX what about the privacy flags ? */
break ;
}
2008-02-09 11:27:10 +00:00
if ( res2 == '1' ) { /* the only case where we actually connect */
/* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll
2006-11-04 11:00:49 +00:00
just clog things up, and it's not useful information, not being tied to a CID */
2007-12-12 20:05:13 +00:00
if ( strncmp ( pa -> privcid , "NOCALLERID" , 10 ) == 0 || ast_test_flag64 ( opts , OPT_SCREEN_NOINTRO )) {
2006-11-04 11:00:49 +00:00
ast_filedelete ( pa -> privintro , NULL );
2007-12-12 20:05:13 +00:00
if ( ast_fileexists ( pa -> privintro , NULL , NULL ) > 0 )
2006-11-04 11:00:49 +00:00
ast_log ( LOG_NOTICE , "privacy: ast_filedelete didn't do its job on %s \n " , pa -> privintro );
2007-07-26 15:49:18 +00:00
else
ast_verb ( 3 , "Successfully deleted %s intro file \n " , pa -> privintro );
2006-11-04 11:00:49 +00:00
}
2008-02-09 11:27:10 +00:00
return 0 ; /* the good exit path */
2006-11-04 11:00:49 +00:00
} else {
ast_hangup ( peer ); /* hang up on the callee -- he didn't want to talk anyway! */
return - 1 ;
}
}
2006-12-19 09:15:23 +00:00
/*! \brief returns 1 if successful, 0 or <0 if the caller should 'goto out' */
static int setup_privacy_args ( struct privacy_args * pa ,
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
struct ast_flags64 * opts , char * opt_args [], struct ast_channel * chan )
2006-12-19 09:15:23 +00:00
{
char callerid [ 60 ];
int res ;
char * l ;
2008-03-05 16:23:44 +00:00
int silencethreshold ;
2006-12-19 09:15:23 +00:00
if ( ! ast_strlen_zero ( chan -> cid . cid_num )) {
l = ast_strdupa ( chan -> cid . cid_num );
ast_shrink_phone_number ( l );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( opts , OPT_PRIVACY ) ) {
2007-12-14 14:48:38 +00:00
ast_verb ( 3 , "Privacy DB is '%s', clid is '%s' \n " , opt_args [ OPT_ARG_PRIVACY ], l );
2006-12-19 09:15:23 +00:00
pa -> privdb_val = ast_privacy_check ( opt_args [ OPT_ARG_PRIVACY ], l );
} else {
2007-12-14 14:48:38 +00:00
ast_verb ( 3 , "Privacy Screening, clid is '%s' \n " , l );
2006-12-19 09:15:23 +00:00
pa -> privdb_val = AST_PRIVACY_UNKNOWN ;
}
} else {
char * tnam , * tn2 ;
tnam = ast_strdupa ( chan -> name );
/* clean the channel name so slashes don't try to end up in disk file name */
for ( tn2 = tnam ; * tn2 ; tn2 ++ ) {
2007-12-14 14:48:38 +00:00
if ( * tn2 == '/' ) /* any other chars to be afraid of? */
2006-12-19 09:15:23 +00:00
* tn2 = '=' ;
}
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "Privacy-- callerid is empty \n " );
2006-12-19 09:15:23 +00:00
snprintf ( callerid , sizeof ( callerid ), "NOCALLERID_%s%s" , chan -> exten , tnam );
l = callerid ;
pa -> privdb_val = AST_PRIVACY_UNKNOWN ;
}
2008-02-09 11:27:10 +00:00
2007-12-12 20:05:13 +00:00
ast_copy_string ( pa -> privcid , l , sizeof ( pa -> privcid ));
2006-12-19 09:15:23 +00:00
2007-12-12 20:05:13 +00:00
if ( strncmp ( pa -> privcid , "NOCALLERID" , 10 ) != 0 && ast_test_flag64 ( opts , OPT_SCREEN_NOCLID )) {
2008-02-09 11:27:10 +00:00
/* if callerid is set and OPT_SCREEN_NOCLID is set also */
2007-12-14 14:48:38 +00:00
ast_verb ( 3 , "CallerID set (%s); N option set; Screening should be off \n " , pa -> privcid );
2006-12-19 09:15:23 +00:00
pa -> privdb_val = AST_PRIVACY_ALLOW ;
2007-12-14 14:48:38 +00:00
} else if ( ast_test_flag64 ( opts , OPT_SCREEN_NOCLID ) && strncmp ( pa -> privcid , "NOCALLERID" , 10 ) == 0 ) {
ast_verb ( 3 , "CallerID blank; N option set; Screening should happen; dbval is %d \n " , pa -> privdb_val );
2006-12-19 09:15:23 +00:00
}
2007-12-12 20:05:13 +00:00
if ( pa -> privdb_val == AST_PRIVACY_DENY ) {
2007-12-14 14:48:38 +00:00
ast_verb ( 3 , "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable \n " );
2006-12-19 09:15:23 +00:00
ast_copy_string ( pa -> status , "NOANSWER" , sizeof ( pa -> status ));
return 0 ;
2007-12-12 20:05:13 +00:00
} else if ( pa -> privdb_val == AST_PRIVACY_KILL ) {
2006-12-19 09:15:23 +00:00
ast_copy_string ( pa -> status , "DONTCALL" , sizeof ( pa -> status ));
return 0 ; /* Is this right? */
2007-12-12 20:05:13 +00:00
} else if ( pa -> privdb_val == AST_PRIVACY_TORTURE ) {
2006-12-19 09:15:23 +00:00
ast_copy_string ( pa -> status , "TORTURE" , sizeof ( pa -> status ));
return 0 ; /* is this right??? */
2007-12-12 20:05:13 +00:00
} else if ( pa -> privdb_val == AST_PRIVACY_UNKNOWN ) {
2008-02-09 11:27:10 +00:00
/* Get the user's intro, store it in priv-callerintros/$CID,
unless it is already there-- this should be done before the
2006-12-19 09:15:23 +00:00
call is actually dialed */
/* make sure the priv-callerintros dir actually exists */
snprintf ( pa -> privintro , sizeof ( pa -> privintro ), "%s/sounds/priv-callerintros" , ast_config_AST_DATA_DIR );
2007-06-22 04:35:12 +00:00
if (( res = ast_mkdir ( pa -> privintro , 0755 ))) {
ast_log ( LOG_WARNING , "privacy: can't create directory priv-callerintros: %s \n " , strerror ( res ));
2006-12-19 09:15:23 +00:00
return - 1 ;
}
2007-06-22 04:35:12 +00:00
snprintf ( pa -> privintro , sizeof ( pa -> privintro ), "priv-callerintros/%s" , pa -> privcid );
if ( ast_fileexists ( pa -> privintro , NULL , NULL ) > 0 && strncmp ( pa -> privcid , "NOCALLERID" , 10 ) != 0 ) {
2006-12-19 09:15:23 +00:00
/* the DELUX version of this code would allow this caller the
option to hear and retape their previously recorded intro.
*/
} else {
int duration ; /* for feedback from play_and_wait */
/* the file doesn't exist yet. Let the caller submit his
vocal intro for posterity */
/* priv-recordintro script:
"At the tone, please say your name:"
*/
2008-03-05 16:23:44 +00:00
silencethreshold = ast_dsp_get_threshold_from_settings ( THRESHOLD_SILENCE );
2007-02-17 03:57:23 +00:00
ast_answer ( chan );
2008-03-05 16:23:44 +00:00
res = ast_play_and_record ( chan , "priv-recordintro" , pa -> privintro , 4 , "gsm" , & duration , silencethreshold , 2000 , 0 ); /* NOTE: I've reduced the total time to 4 sec */
2006-12-19 09:15:23 +00:00
/* don't think we'll need a lock removed, we took care of
conflicts by naming the pa.privintro file */
if ( res == - 1 ) {
/* Delete the file regardless since they hung up during recording */
ast_filedelete ( pa -> privintro , NULL );
2007-12-12 20:05:13 +00:00
if ( ast_fileexists ( pa -> privintro , NULL , NULL ) > 0 )
ast_log ( LOG_NOTICE , "privacy: ast_filedelete didn't do its job on %s \n " , pa -> privintro );
2007-07-26 15:49:18 +00:00
else
ast_verb ( 3 , "Successfully deleted %s intro file \n " , pa -> privintro );
2006-12-19 09:15:23 +00:00
return - 1 ;
}
if ( ! ast_streamfile ( chan , "vm-dialout" , chan -> language ) )
ast_waitstream ( chan , "" );
}
}
2008-02-09 11:27:10 +00:00
return 1 ; /* success */
2006-12-19 09:15:23 +00:00
}
2008-03-01 01:30:37 +00:00
static void set_dial_features ( struct ast_flags64 * opts , struct ast_dial_features * features )
{
struct ast_flags64 perm_opts = {. flags = 0 };
ast_copy_flags64 ( & perm_opts , opts ,
OPT_CALLER_TRANSFER | OPT_CALLER_PARK | OPT_CALLER_MONITOR | OPT_CALLER_MIXMONITOR | OPT_CALLER_HANGUP |
OPT_CALLEE_TRANSFER | OPT_CALLEE_PARK | OPT_CALLEE_MONITOR | OPT_CALLEE_MIXMONITOR | OPT_CALLEE_HANGUP );
memset ( features -> options , 0 , sizeof ( features -> options ));
ast_app_options2str64 ( dial_exec_options , & perm_opts , features -> options , sizeof ( features -> options ));
}
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
static int dial_exec_full ( struct ast_channel * chan , void * data , struct ast_flags64 * peerflags , int * continue_exec )
1999-12-04 21:35:07 +00:00
{
2008-02-09 11:27:10 +00:00
int res = - 1 ; /* default: error */
char * rest , * cur ; /* scan the list of destinations */
struct chanlist * outgoing = NULL ; /* list of destinations */
2004-06-21 13:30:58 +00:00
struct ast_channel * peer ;
2008-02-09 11:27:10 +00:00
int to ; /* timeout */
2006-11-03 22:36:17 +00:00
struct cause_args num = { chan , 0 , 0 , 0 };
2004-10-26 22:25:43 +00:00
int cause ;
2007-05-17 16:49:50 +00:00
char numsubst [ 256 ];
2007-06-04 18:00:24 +00:00
char cidname [ AST_MAX_EXTENSION ] = "" ;
2006-11-04 00:50:18 +00:00
2007-12-12 20:05:13 +00:00
struct ast_bridge_config config = { { 0 , } };
2006-04-11 16:15:11 +00:00
unsigned int calldurationlimit = 0 ;
char * dtmfcalled = NULL , * dtmfcalling = NULL ;
2006-11-04 11:00:49 +00:00
struct privacy_args pa = {
. sentringing = 0 ,
. privdb_val = 0 ,
2007-02-03 20:46:36 +00:00
. status = "INVALIDARGS" ,
2006-11-04 11:00:49 +00:00
};
2006-04-11 16:15:11 +00:00
int sentringing = 0 , moh = 0 ;
2005-12-20 17:52:31 +00:00
const char * outbound_group = NULL ;
2006-04-19 16:54:04 +00:00
int result = 0 ;
2006-04-19 16:36:15 +00:00
time_t start_time ;
2005-11-02 21:46:52 +00:00
char * parse ;
2006-04-22 11:30:06 +00:00
int opermode = 0 ;
2005-11-02 21:46:52 +00:00
AST_DECLARE_APP_ARGS ( args ,
2008-02-09 11:27:10 +00:00
AST_APP_ARG ( peers );
AST_APP_ARG ( timeout );
AST_APP_ARG ( options );
AST_APP_ARG ( url );
2005-11-02 21:46:52 +00:00
);
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
struct ast_flags64 opts = { 0 , };
2005-11-02 21:46:52 +00:00
char * opt_args [ OPT_ARG_ARRAY_SIZE ];
2007-12-04 17:35:40 +00:00
struct ast_datastore * datastore = NULL ;
2008-03-01 01:30:37 +00:00
struct ast_datastore * ds_caller_features = NULL ;
struct ast_datastore * ds_callee_features = NULL ;
struct ast_dial_features * caller_features ;
2007-12-04 17:08:36 +00:00
int fulldial = 0 , num_dialed = 0 ;
2005-03-17 22:39:04 +00:00
2005-10-26 19:48:14 +00:00
if ( ast_strlen_zero ( data )) {
2005-11-02 21:46:52 +00:00
ast_log ( LOG_WARNING , "Dial requires an argument (technology/number) \n " );
2007-02-03 20:46:36 +00:00
pbx_builtin_setvar_helper ( chan , "DIALSTATUS" , pa . status );
1999-12-04 21:35:07 +00:00
return - 1 ;
}
2004-09-22 05:19:06 +00:00
2006-05-10 13:22:15 +00:00
parse = ast_strdupa ( data );
2008-02-09 11:27:10 +00:00
2005-11-02 21:46:52 +00:00
AST_STANDARD_APP_ARGS ( args , parse );
2006-04-19 14:02:49 +00:00
if ( ! ast_strlen_zero ( args . options ) &&
2008-02-09 11:27:10 +00:00
ast_app_parse_options64 ( dial_exec_options , & opts , opt_args , args . options )) {
2007-02-03 20:46:36 +00:00
pbx_builtin_setvar_helper ( chan , "DIALSTATUS" , pa . status );
2006-04-19 14:02:49 +00:00
goto done ;
2007-02-03 20:46:36 +00:00
}
2003-01-17 05:10:52 +00:00
2005-11-02 21:46:52 +00:00
if ( ast_strlen_zero ( args . peers )) {
ast_log ( LOG_WARNING , "Dial requires an argument (technology/number) \n " );
2007-02-03 20:46:36 +00:00
pbx_builtin_setvar_helper ( chan , "DIALSTATUS" , pa . status );
2006-04-19 14:02:49 +00:00
goto done ;
2005-11-02 21:46:52 +00:00
}
2004-04-26 23:22:34 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_OPERMODE )) {
2006-11-04 01:16:20 +00:00
opermode = ast_strlen_zero ( opt_args [ OPT_ARG_OPERMODE ]) ? 1 : atoi ( opt_args [ OPT_ARG_OPERMODE ]);
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "Setting operator services mode to %d. \n " , opermode );
2006-04-22 11:30:06 +00:00
}
2006-05-31 15:52:32 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_DURATION_STOP ) && ! ast_strlen_zero ( opt_args [ OPT_ARG_DURATION_STOP ])) {
2005-11-02 21:46:52 +00:00
calldurationlimit = atoi ( opt_args [ OPT_ARG_DURATION_STOP ]);
2006-04-11 16:15:11 +00:00
if ( ! calldurationlimit ) {
ast_log ( LOG_WARNING , "Dial does not accept S(%s), hanging up. \n " , opt_args [ OPT_ARG_DURATION_STOP ]);
2007-02-03 20:46:36 +00:00
pbx_builtin_setvar_helper ( chan , "DIALSTATUS" , pa . status );
2006-04-19 14:02:49 +00:00
goto done ;
2006-04-11 16:15:11 +00:00
}
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "Setting call duration limit to %d seconds. \n " , calldurationlimit );
2005-11-02 21:46:52 +00:00
}
2005-03-17 22:39:04 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_SENDDTMF ) && ! ast_strlen_zero ( opt_args [ OPT_ARG_SENDDTMF ])) {
2006-04-19 16:54:04 +00:00
dtmfcalling = opt_args [ OPT_ARG_SENDDTMF ];
dtmfcalled = strsep ( & dtmfcalling , ":" );
2005-11-02 21:46:52 +00:00
}
2005-03-17 22:39:04 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_DURATION_LIMIT ) && ! ast_strlen_zero ( opt_args [ OPT_ARG_DURATION_LIMIT ])) {
2006-11-04 00:50:18 +00:00
if ( do_timelimit ( chan , & config , opt_args [ OPT_ARG_DURATION_LIMIT ], & calldurationlimit ))
2006-04-19 14:02:49 +00:00
goto done ;
2003-01-17 05:10:52 +00:00
}
2005-11-02 21:46:52 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_RESETCDR ) && chan -> cdr )
2005-11-06 21:00:35 +00:00
ast_cdr_reset ( chan -> cdr , NULL );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_PRIVACY ) && ast_strlen_zero ( opt_args [ OPT_ARG_PRIVACY ]))
2005-11-02 21:46:52 +00:00
opt_args [ OPT_ARG_PRIVACY ] = ast_strdupa ( chan -> exten );
2005-07-12 03:23:31 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_PRIVACY ) || ast_test_flag64 ( & opts , OPT_SCREENING )) {
2006-12-19 09:15:23 +00:00
res = setup_privacy_args ( & pa , & opts , opt_args , chan );
if ( res <= 0 )
2005-07-12 03:23:31 +00:00
goto out ;
2008-02-09 11:27:10 +00:00
res = - 1 ; /* reset default */
2003-01-17 05:10:52 +00:00
}
2004-11-07 21:49:43 +00:00
2007-02-15 16:24:13 +00:00
if ( continue_exec )
* continue_exec = 0 ;
2008-02-09 11:27:10 +00:00
2004-11-07 21:49:43 +00:00
/* If a channel group has been specified, get it for use when we create peer channels */
2007-04-13 19:18:46 +00:00
if (( outbound_group = pbx_builtin_getvar_helper ( chan , "OUTBOUND_GROUP_ONCE" ))) {
outbound_group = ast_strdupa ( outbound_group );
pbx_builtin_setvar_helper ( chan , "OUTBOUND_GROUP_ONCE" , NULL );
} else {
outbound_group = pbx_builtin_getvar_helper ( chan , "OUTBOUND_GROUP" );
}
2008-02-09 11:27:10 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_copy_flags64 ( peerflags , & opts , OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING );
2008-03-01 01:30:37 +00:00
/* Create datastore for channel dial features for caller */
if ( ! ( ds_caller_features = ast_channel_datastore_alloc ( & dial_features_info , NULL ))) {
ast_log ( LOG_WARNING , "Unable to create channel datastore for dial features. Aborting! \n " );
goto out ;
}
if ( ! ( caller_features = ast_malloc ( sizeof ( * caller_features )))) {
ast_log ( LOG_WARNING , "Unable to allocate memory for feature flags. Aborting! \n " );
goto out ;
}
ast_copy_flags ( & ( caller_features -> features_callee ), & ( config . features_caller ), AST_FLAGS_ALL );
caller_features -> is_caller = 1 ;
set_dial_features ( & opts , caller_features );
ds_caller_features -> inheritance = DATASTORE_INHERIT_FOREVER ;
ds_caller_features -> data = caller_features ;
ast_channel_lock ( chan );
ast_channel_datastore_add ( chan , ds_caller_features );
ast_channel_unlock ( chan );
2006-04-19 14:02:49 +00:00
/* loop through the list of dial destinations */
rest = args . peers ;
while (( cur = strsep ( & rest , "&" )) ) {
2006-12-19 16:36:45 +00:00
struct chanlist * tmp ;
2008-02-09 11:27:10 +00:00
struct ast_channel * tc ; /* channel for this destination */
1999-12-18 07:01:48 +00:00
/* Get a technology/[device:]number pair */
2006-04-19 16:36:15 +00:00
char * number = cur ;
2007-12-04 17:08:36 +00:00
char * interface = ast_strdupa ( number );
2006-04-19 16:36:15 +00:00
char * tech = strsep ( & number , "/" );
2007-12-04 17:08:36 +00:00
/* find if we already dialed this interface */
struct ast_dialed_interface * di ;
2008-03-01 01:30:37 +00:00
struct ast_dial_features * callee_features ;
2007-12-04 17:08:36 +00:00
AST_LIST_HEAD (, ast_dialed_interface ) * dialed_interfaces ;
num_dialed ++ ;
1999-12-04 21:35:07 +00:00
if ( ! number ) {
2005-11-02 21:46:52 +00:00
ast_log ( LOG_WARNING , "Dial argument takes format (technology/[device:]number1) \n " );
1999-12-04 21:35:07 +00:00
goto out ;
}
2006-04-19 14:02:49 +00:00
if ( ! ( tmp = ast_calloc ( 1 , sizeof ( * tmp ))))
1999-12-04 21:35:07 +00:00
goto out ;
2005-11-02 21:46:52 +00:00
if ( opts . flags ) {
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_copy_flags64 ( tmp , & opts ,
2008-02-09 11:27:10 +00:00
OPT_CANCEL_ELSEWHERE |
OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
OPT_CALLEE_PARK | OPT_CALLER_PARK |
OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID );
ast_set2_flag64 ( tmp , args . url , DIAL_NOFORWARDHTML );
2002-05-17 14:33:10 +00:00
}
2005-07-07 23:32:37 +00:00
ast_copy_string ( numsubst , number , sizeof ( numsubst ));
1999-12-04 21:35:07 +00:00
/* Request the peer */
2007-12-07 16:40:41 +00:00
ast_channel_lock ( chan );
datastore = ast_channel_datastore_find ( chan , & dialed_interface_info , NULL );
ast_channel_unlock ( chan );
if ( datastore )
dialed_interfaces = datastore -> data ;
else {
if ( ! ( datastore = ast_channel_datastore_alloc ( & dialed_interface_info , NULL ))) {
2008-02-09 11:27:10 +00:00
ast_log ( LOG_WARNING , "Unable to create channel datastore for dialed interfaces. Aborting! \n " );
2007-12-12 20:05:13 +00:00
ast_free ( tmp );
2007-12-04 17:08:36 +00:00
goto out ;
}
2007-12-07 16:40:41 +00:00
datastore -> inheritance = DATASTORE_INHERIT_FOREVER ;
if ( ! ( dialed_interfaces = ast_calloc ( 1 , sizeof ( * dialed_interfaces )))) {
2007-12-12 20:05:13 +00:00
ast_free ( tmp );
2007-12-07 16:40:41 +00:00
goto out ;
2007-12-04 17:08:36 +00:00
}
2007-12-07 16:40:41 +00:00
datastore -> data = dialed_interfaces ;
AST_LIST_HEAD_INIT ( dialed_interfaces );
ast_channel_lock ( chan );
ast_channel_datastore_add ( chan , datastore );
ast_channel_unlock ( chan );
}
2007-12-04 17:08:36 +00:00
AST_LIST_LOCK ( dialed_interfaces );
AST_LIST_TRAVERSE ( dialed_interfaces , di , list ) {
2007-12-07 16:40:41 +00:00
if ( ! strcasecmp ( di -> interface , interface )) {
2008-02-09 11:27:10 +00:00
ast_log ( LOG_WARNING , "Skipping dialing interface '%s' again since it has already been dialed \n " ,
2007-12-07 16:40:41 +00:00
di -> interface );
2007-12-04 17:08:36 +00:00
break ;
}
}
2007-12-07 16:40:41 +00:00
AST_LIST_UNLOCK ( dialed_interfaces );
if ( di ) {
fulldial ++ ;
2007-12-12 20:05:13 +00:00
ast_free ( tmp );
2007-12-07 16:40:41 +00:00
continue ;
}
/* It is always ok to dial a Local interface. We only keep track of
* which "real" interfaces have been dialed. The Local channel will
* inherit this list so that if it ends up dialing a real interface,
* it won't call one that has already been called. */
if ( strcasecmp ( tech , "Local" )) {
if ( ! ( di = ast_calloc ( 1 , sizeof ( * di ) + strlen ( interface )))) {
2007-12-04 17:08:36 +00:00
AST_LIST_UNLOCK ( dialed_interfaces );
2007-12-12 20:05:13 +00:00
ast_free ( tmp );
2007-12-04 17:08:36 +00:00
goto out ;
}
strcpy ( di -> interface , interface );
2007-12-07 16:40:41 +00:00
AST_LIST_LOCK ( dialed_interfaces );
2007-12-04 17:08:36 +00:00
AST_LIST_INSERT_TAIL ( dialed_interfaces , di , list );
2007-12-07 02:52:38 +00:00
AST_LIST_UNLOCK ( dialed_interfaces );
2007-12-04 17:08:36 +00:00
}
2006-12-19 09:58:40 +00:00
tc = ast_request ( tech , chan -> nativeformats , numsubst , & cause );
if ( ! tc ) {
1999-12-04 21:35:07 +00:00
/* If we can't, just go on to the next call */
2006-12-19 09:58:40 +00:00
ast_log ( LOG_WARNING , "Unable to create channel of type '%s' (cause %d - %s) \n " ,
2008-02-09 11:27:10 +00:00
tech , cause , ast_cause2str ( cause ));
2006-11-03 22:36:17 +00:00
handle_cause ( cause , & num );
2008-02-09 11:27:10 +00:00
if ( ! rest ) /* we are on the last destination */
2005-10-05 21:18:28 +00:00
chan -> hangupcause = cause ;
2007-06-06 21:20:11 +00:00
ast_free ( tmp );
1999-12-04 21:35:07 +00:00
continue ;
}
2006-12-19 09:58:40 +00:00
pbx_builtin_setvar_helper ( tc , "DIALEDPEERNUMBER" , numsubst );
2004-11-01 02:23:28 +00:00
2005-12-20 17:52:31 +00:00
/* Setup outgoing SDP to match incoming one */
2006-12-19 09:58:40 +00:00
ast_rtp_make_compatible ( tc , chan , ! outgoing && ! rest );
2005-12-20 17:52:31 +00:00
2005-01-08 17:23:29 +00:00
/* Inherit specially named variables from parent channel */
2006-12-19 09:58:40 +00:00
ast_channel_inherit_variables ( chan , tc );
2004-11-01 02:23:28 +00:00
2006-12-19 09:58:40 +00:00
tc -> appl = "AppDial" ;
tc -> data = "(Outgoing Line)" ;
tc -> whentohangup = 0 ;
2006-04-19 16:19:52 +00:00
2006-12-19 09:58:40 +00:00
S_REPLACE ( tc -> cid . cid_num , ast_strdup ( chan -> cid . cid_num ));
S_REPLACE ( tc -> cid . cid_name , ast_strdup ( chan -> cid . cid_name ));
S_REPLACE ( tc -> cid . cid_ani , ast_strdup ( chan -> cid . cid_ani ));
S_REPLACE ( tc -> cid . cid_rdnis , ast_strdup ( chan -> cid . cid_rdnis ));
2004-10-02 00:58:31 +00:00
2003-12-04 22:26:38 +00:00
/* Copy language from incoming to outgoing */
2006-12-19 09:58:40 +00:00
ast_string_field_set ( tc , language , chan -> language );
ast_string_field_set ( tc , accountcode , chan -> accountcode );
tc -> cdrflags = chan -> cdrflags ;
if ( ast_strlen_zero ( tc -> musicclass ))
ast_string_field_set ( tc , musicclass , chan -> musicclass );
/* Pass callingpres, type of number, tns, ADSI CPE, transfer capability */
tc -> cid . cid_pres = chan -> cid . cid_pres ;
tc -> cid . cid_ton = chan -> cid . cid_ton ;
tc -> cid . cid_tns = chan -> cid . cid_tns ;
2007-10-11 22:42:44 +00:00
tc -> cid . cid_ani2 = chan -> cid . cid_ani2 ;
2006-12-19 09:58:40 +00:00
tc -> adsicpe = chan -> adsicpe ;
tc -> transfercapability = chan -> transfercapability ;
2004-11-07 21:49:43 +00:00
/* If we have an outbound group, set this peer channel to it */
if ( outbound_group )
2006-12-19 09:58:40 +00:00
ast_app_group_set_channel ( tc , outbound_group );
2004-11-07 21:49:43 +00:00
2006-10-13 21:20:18 +00:00
/* Inherit context and extension */
2007-02-16 17:07:10 +00:00
if ( ! ast_strlen_zero ( chan -> macrocontext ))
ast_copy_string ( tc -> dialcontext , chan -> macrocontext , sizeof ( tc -> dialcontext ));
else
ast_copy_string ( tc -> dialcontext , chan -> context , sizeof ( tc -> dialcontext ));
2007-02-16 18:53:17 +00:00
if ( ! ast_strlen_zero ( chan -> macroexten ))
ast_copy_string ( tc -> exten , chan -> macroexten , sizeof ( tc -> exten ));
else
ast_copy_string ( tc -> exten , chan -> exten , sizeof ( tc -> exten ));
2006-10-13 21:20:18 +00:00
2008-03-01 01:30:37 +00:00
/* Save callee features */
if ( ! ( ds_callee_features = ast_channel_datastore_alloc ( & dial_features_info , NULL ))) {
ast_log ( LOG_WARNING , "Unable to create channel datastore for dial features. Aborting! \n " );
ast_free ( tmp );
goto out ;
}
if ( ! ( callee_features = ast_malloc ( sizeof ( * callee_features )))) {
ast_log ( LOG_WARNING , "Unable to allocate memory for feature flags. Aborting! \n " );
ast_free ( tmp );
goto out ;
}
ast_copy_flags ( & ( callee_features -> features_callee ), & ( config . features_callee ), AST_FLAGS_ALL );
callee_features -> is_caller = 0 ;
set_dial_features ( & opts , callee_features );
ds_callee_features -> inheritance = DATASTORE_INHERIT_FOREVER ;
ds_callee_features -> data = callee_features ;
ast_channel_lock ( chan );
ast_channel_datastore_add ( tc , ds_callee_features );
ast_channel_unlock ( chan );
2008-02-09 11:27:10 +00:00
res = ast_call ( tc , numsubst , 0 ); /* Place the call, but don't wait on the answer */
2003-08-14 20:48:44 +00:00
/* Save the info in cdr's that we called them */
if ( chan -> cdr )
2006-12-19 09:58:40 +00:00
ast_cdr_setdestchan ( chan -> cdr , tc -> name );
2003-08-14 20:48:44 +00:00
2004-06-20 06:24:25 +00:00
/* check the results of ast_call */
1999-12-04 21:35:07 +00:00
if ( res ) {
/* Again, keep going even if there's an error */
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , "ast call on peer returned %d \n " , res );
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "Couldn't call %s \n " , numsubst );
2006-12-19 09:58:40 +00:00
ast_hangup ( tc );
tc = NULL ;
2007-06-06 21:20:11 +00:00
ast_free ( tmp );
1999-12-04 21:35:07 +00:00
continue ;
2005-01-16 07:58:51 +00:00
} else {
2007-12-06 15:04:34 +00:00
senddialevent ( chan , tc , numsubst );
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , "Called %s \n " , numsubst );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ! ast_test_flag64 ( peerflags , OPT_ORIGINAL_CLID ))
2006-12-19 09:58:40 +00:00
ast_set_callerid ( tc , S_OR ( chan -> macroexten , chan -> exten ), get_cid_name ( cidname , sizeof ( cidname ), chan ), NULL );
2005-01-16 07:58:51 +00:00
}
2008-02-09 11:27:10 +00:00
/* Put them in the list of outgoing thingies... We're ready now.
1999-12-04 21:35:07 +00:00
XXX If we're forcibly removed, these outgoing calls won't get
hung up XXX */
2008-02-09 11:27:10 +00:00
ast_set_flag64 ( tmp , DIAL_STILLGOING );
2006-12-19 09:58:40 +00:00
tmp -> chan = tc ;
1999-12-04 21:35:07 +00:00
tmp -> next = outgoing ;
outgoing = tmp ;
2002-09-02 15:20:28 +00:00
/* If this line is up, don't try anybody else */
if ( outgoing -> chan -> _state == AST_STATE_UP )
break ;
2006-04-19 14:02:49 +00:00
}
2001-03-30 18:47:35 +00:00
2006-04-19 14:02:49 +00:00
if ( ast_strlen_zero ( args . timeout )) {
to = - 1 ;
} else {
2005-11-02 21:46:52 +00:00
to = atoi ( args . timeout );
2004-04-02 07:47:23 +00:00
if ( to > 0 )
to *= 1000 ;
else
2005-11-02 21:46:52 +00:00
ast_log ( LOG_WARNING , "Invalid timeout specified: '%s' \n " , args . timeout );
2006-04-19 14:02:49 +00:00
}
2004-06-21 18:28:35 +00:00
2006-04-19 14:02:49 +00:00
if ( ! outgoing ) {
2006-11-04 11:00:49 +00:00
strcpy ( pa . status , "CHANUNAVAIL" );
2007-12-12 20:05:13 +00:00
if ( fulldial == num_dialed ) {
2007-12-04 17:08:36 +00:00
res = - 1 ;
goto out ;
}
2006-04-19 14:02:49 +00:00
} else {
2004-06-23 03:16:58 +00:00
/* Our status will at least be NOANSWER */
2006-11-04 11:00:49 +00:00
strcpy ( pa . status , "NOANSWER" );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( outgoing , OPT_MUSICBACK )) {
2006-07-19 20:44:39 +00:00
moh = 1 ;
2007-02-09 19:39:26 +00:00
if ( ! ast_strlen_zero ( opt_args [ OPT_ARG_MUSICBACK ])) {
char * original_moh = ast_strdupa ( chan -> musicclass );
ast_string_field_set ( chan , musicclass , opt_args [ OPT_ARG_MUSICBACK ]);
ast_moh_start ( chan , opt_args [ OPT_ARG_MUSICBACK ], NULL );
ast_string_field_set ( chan , musicclass , original_moh );
} else {
ast_moh_start ( chan , NULL , NULL );
}
2006-12-01 23:39:59 +00:00
ast_indicate ( chan , AST_CONTROL_PROGRESS );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
} else if ( ast_test_flag64 ( outgoing , OPT_RINGBACK )) {
2004-06-22 13:53:45 +00:00
ast_indicate ( chan , AST_CONTROL_RINGING );
sentringing ++ ;
}
2006-04-19 14:02:49 +00:00
}
2004-06-21 18:28:35 +00:00
2004-07-14 01:10:24 +00:00
time ( & start_time );
2007-06-12 15:58:28 +00:00
peer = wait_for_answer ( chan , outgoing , & to , peerflags , & pa , & num , & result );
2007-12-04 17:08:36 +00:00
ast_channel_datastore_remove ( chan , datastore );
ast_channel_datastore_free ( datastore );
1999-12-04 21:35:07 +00:00
if ( ! peer ) {
2005-01-18 03:12:53 +00:00
if ( result ) {
res = result ;
2006-04-19 14:02:49 +00:00
} else if ( to ) { /* Musta gotten hung up */
1999-12-04 21:35:07 +00:00
res = - 1 ;
2006-04-19 14:02:49 +00:00
} else { /* Nobody answered, next please? */
2005-09-07 19:13:00 +00:00
res = 0 ;
2006-04-19 14:02:49 +00:00
}
2006-04-19 16:54:04 +00:00
/* almost done, although the 'else' block is 400 lines */
2006-04-19 14:02:49 +00:00
} else {
2006-04-19 16:36:15 +00:00
const char * number ;
time_t end_time , answer_time = time ( NULL );
2008-02-09 11:27:10 +00:00
char toast [ 80 ]; /* buffer to set variables */
2006-04-19 16:36:15 +00:00
2006-11-04 11:00:49 +00:00
strcpy ( pa . status , "ANSWER" );
1999-12-04 21:35:07 +00:00
/* Ah ha! Someone answered within the desired timeframe. Of course after this
2008-02-09 11:27:10 +00:00
we will always return with -1 so that it is hung up properly after the
1999-12-04 21:35:07 +00:00
conversation. */
2007-07-09 08:27:37 +00:00
hanguptree ( outgoing , peer , 1 );
1999-12-04 21:35:07 +00:00
outgoing = NULL ;
2001-12-20 15:21:47 +00:00
/* If appropriate, log that we have a destination channel */
if ( chan -> cdr )
ast_cdr_setdestchan ( chan -> cdr , peer -> name );
2003-03-12 06:00:18 +00:00
if ( peer -> name )
pbx_builtin_setvar_helper ( chan , "DIALEDPEERNAME" , peer -> name );
2005-01-27 16:33:12 +00:00
2006-04-19 16:36:15 +00:00
number = pbx_builtin_getvar_helper ( peer , "DIALEDPEERNUMBER" );
2005-01-27 16:33:12 +00:00
if ( ! number )
number = numsubst ;
pbx_builtin_setvar_helper ( chan , "DIALEDPEERNUMBER" , number );
2008-02-09 11:27:10 +00:00
if ( ! ast_strlen_zero ( args . url ) && ast_channel_supports_html ( peer ) ) {
ast_debug ( 1 , "app_dial: sendurl=%s. \n " , args . url );
ast_channel_sendurl ( peer , args . url );
}
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ( ast_test_flag64 ( & opts , OPT_PRIVACY ) || ast_test_flag64 ( & opts , OPT_SCREENING )) && pa . privdb_val == AST_PRIVACY_UNKNOWN ) {
2006-11-04 11:00:49 +00:00
if ( do_privacy ( chan , peer , & opts , opt_args , & pa )) {
2006-04-19 18:00:32 +00:00
res = 0 ;
goto out ;
}
2005-07-12 03:23:31 +00:00
}
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ! ast_test_flag64 ( & opts , OPT_ANNOUNCE ) || ast_strlen_zero ( opt_args [ OPT_ARG_ANNOUNCE ])) {
2006-04-19 14:02:49 +00:00
res = 0 ;
} else {
2006-04-19 16:54:04 +00:00
int digit = 0 ;
2004-12-19 21:13:41 +00:00
/* Start autoservice on the other chan */
2004-05-07 20:39:14 +00:00
res = ast_autoservice_start ( chan );
2004-12-19 21:13:41 +00:00
/* Now Stream the File */
2004-05-07 20:39:14 +00:00
if ( ! res )
2005-11-02 21:46:52 +00:00
res = ast_streamfile ( peer , opt_args [ OPT_ARG_ANNOUNCE ], peer -> language );
2004-05-20 00:29:09 +00:00
if ( ! res ) {
2008-02-09 11:27:10 +00:00
digit = ast_waitstream ( peer , AST_DIGIT_ANY );
2004-05-20 00:29:09 +00:00
}
2004-12-19 21:13:41 +00:00
/* Ok, done. stop autoservice */
2004-05-07 20:39:14 +00:00
res = ast_autoservice_stop ( chan );
2004-05-20 00:29:09 +00:00
if ( digit > 0 && ! res )
2008-02-09 11:27:10 +00:00
res = ast_senddigit ( chan , digit , 0 );
2004-05-20 00:29:09 +00:00
else
res = digit ;
2006-04-19 14:02:49 +00:00
}
2005-03-17 22:39:04 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( chan && peer && ast_test_flag64 ( & opts , OPT_GOTO ) && ! ast_strlen_zero ( opt_args [ OPT_ARG_GOTO ])) {
2006-04-19 14:02:49 +00:00
replace_macro_delimiter ( opt_args [ OPT_ARG_GOTO ]);
2005-11-02 21:46:52 +00:00
ast_parseable_goto ( chan , opt_args [ OPT_ARG_GOTO ]);
2007-12-05 22:55:49 +00:00
/* peer goes to the same context and extension as chan, so just copy info from chan*/
ast_copy_string ( peer -> context , chan -> context , sizeof ( peer -> context ));
ast_copy_string ( peer -> exten , chan -> exten , sizeof ( peer -> exten ));
peer -> priority = chan -> priority + 2 ;
2005-03-17 22:39:04 +00:00
ast_pbx_start ( peer );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
hanguptree ( outgoing , NULL , ast_test_flag64 ( & opts , OPT_CANCEL_ELSEWHERE ) ? 1 : 0 );
2007-02-15 16:24:13 +00:00
if ( continue_exec )
* continue_exec = 1 ;
res = 0 ;
2006-04-19 14:02:49 +00:00
goto done ;
2005-03-17 22:39:04 +00:00
}
2003-07-02 14:06:12 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_CALLEE_MACRO ) && ! ast_strlen_zero ( opt_args [ OPT_ARG_CALLEE_MACRO ])) {
2006-04-19 16:54:04 +00:00
struct ast_app * theapp ;
2006-04-19 18:07:19 +00:00
const char * macro_result ;
2006-04-19 16:54:04 +00:00
2004-09-10 02:31:30 +00:00
res = ast_autoservice_start ( chan );
if ( res ) {
ast_log ( LOG_ERROR , "Unable to start autoservice on calling channel \n " );
res = - 1 ;
}
2006-04-19 16:54:04 +00:00
theapp = pbx_findapp ( "Macro" );
2004-09-10 02:31:30 +00:00
2008-02-09 11:27:10 +00:00
if ( theapp && ! res ) { /* XXX why check res here ? */
2006-04-19 14:02:49 +00:00
replace_macro_delimiter ( opt_args [ OPT_ARG_CALLEE_MACRO ]);
2006-04-19 16:54:04 +00:00
res = pbx_exec ( peer , theapp , opt_args [ OPT_ARG_CALLEE_MACRO ]);
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , "Macro exited with status %d \n " , res );
2004-09-10 02:31:30 +00:00
res = 0 ;
} else {
ast_log ( LOG_ERROR , "Could not find application Macro \n " );
res = - 1 ;
}
if ( ast_autoservice_stop ( chan ) < 0 ) {
ast_log ( LOG_ERROR , "Could not stop autoservice on calling channel \n " );
res = - 1 ;
}
2004-11-22 22:11:10 +00:00
2006-04-19 18:07:19 +00:00
if ( ! res && ( macro_result = pbx_builtin_getvar_helper ( peer , "MACRO_RESULT" ))) {
2006-11-04 01:16:20 +00:00
char * macro_transfer_dest ;
2005-01-05 23:05:49 +00:00
2006-11-04 01:16:20 +00:00
if ( ! strcasecmp ( macro_result , "BUSY" )) {
2006-11-04 11:00:49 +00:00
ast_copy_string ( pa . status , macro_result , sizeof ( pa . status ));
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_set_flag64 ( peerflags , OPT_GO_ON );
2006-11-04 01:16:20 +00:00
res = - 1 ;
} else if ( ! strcasecmp ( macro_result , "CONGESTION" ) || ! strcasecmp ( macro_result , "CHANUNAVAIL" )) {
2006-11-04 11:00:49 +00:00
ast_copy_string ( pa . status , macro_result , sizeof ( pa . status ));
2008-02-09 11:27:10 +00:00
ast_set_flag64 ( peerflags , OPT_GO_ON );
2006-11-04 01:16:20 +00:00
res = - 1 ;
} else if ( ! strcasecmp ( macro_result , "CONTINUE" )) {
2008-02-09 11:27:10 +00:00
/* hangup peer and keep chan alive assuming the macro has changed
the context / exten / priority or perhaps
2006-11-04 01:16:20 +00:00
the next priority in the current exten is desired.
*/
2008-02-09 11:27:10 +00:00
ast_set_flag64 ( peerflags , OPT_GO_ON );
2006-11-04 01:16:20 +00:00
res = - 1 ;
} else if ( ! strcasecmp ( macro_result , "ABORT" )) {
/* Hangup both ends unless the caller has the g flag */
res = - 1 ;
} else if ( ! strncasecmp ( macro_result , "GOTO:" , 5 ) && ( macro_transfer_dest = ast_strdupa ( macro_result + 5 ))) {
res = - 1 ;
/* perform a transfer to a new extension */
if ( strchr ( macro_transfer_dest , '^' )) { /* context^exten^priority*/
replace_macro_delimiter ( macro_transfer_dest );
if ( ! ast_parseable_goto ( chan , macro_transfer_dest ))
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_set_flag64 ( peerflags , OPT_GO_ON );
2004-11-22 22:11:10 +00:00
}
2006-11-04 01:16:20 +00:00
}
2004-11-22 22:11:10 +00:00
}
2004-09-10 02:31:30 +00:00
}
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_CALLEE_GOSUB ) && ! ast_strlen_zero ( opt_args [ OPT_ARG_CALLEE_GOSUB ])) {
2007-06-19 23:36:34 +00:00
struct ast_app * theapp ;
const char * gosub_result ;
2007-06-20 17:35:08 +00:00
char * gosub_args , * gosub_argstart ;
2007-06-19 23:36:34 +00:00
res = ast_autoservice_start ( chan );
if ( res ) {
ast_log ( LOG_ERROR , "Unable to start autoservice on calling channel \n " );
res = - 1 ;
}
theapp = pbx_findapp ( "Gosub" );
2008-02-09 11:27:10 +00:00
if ( theapp && ! res ) { /* XXX why check res here ? */
2007-06-19 23:36:34 +00:00
replace_macro_delimiter ( opt_args [ OPT_ARG_CALLEE_GOSUB ]);
2007-06-20 17:35:08 +00:00
/* Set where we came from */
ast_copy_string ( peer -> context , "app_dial_gosub_virtual_context" , sizeof ( peer -> context ));
ast_copy_string ( peer -> exten , "s" , sizeof ( peer -> exten ));
peer -> priority = 0 ;
gosub_argstart = strchr ( opt_args [ OPT_ARG_CALLEE_GOSUB ], '|' );
if ( gosub_argstart ) {
* gosub_argstart = 0 ;
asprintf ( & gosub_args , "%s|s|1(%s)" , opt_args [ OPT_ARG_CALLEE_GOSUB ], gosub_argstart + 1 );
* gosub_argstart = '|' ;
} else {
asprintf ( & gosub_args , "%s|s|1" , opt_args [ OPT_ARG_CALLEE_GOSUB ]);
}
2007-06-20 21:38:49 +00:00
2007-06-20 17:35:08 +00:00
if ( gosub_args ) {
res = pbx_exec ( peer , theapp , gosub_args );
ast_pbx_run ( peer );
2007-12-12 20:05:13 +00:00
ast_free ( gosub_args );
2007-06-20 17:35:08 +00:00
if ( option_debug )
ast_log ( LOG_DEBUG , "Gosub exited with status %d \n " , res );
} else
ast_log ( LOG_ERROR , "Could not Allocate string for Gosub arguments -- Gosub Call Aborted! \n " );
2008-02-09 11:27:10 +00:00
2007-06-19 23:36:34 +00:00
res = 0 ;
} else {
ast_log ( LOG_ERROR , "Could not find application Gosub \n " );
res = - 1 ;
}
if ( ast_autoservice_stop ( chan ) < 0 ) {
ast_log ( LOG_ERROR , "Could not stop autoservice on calling channel \n " );
res = - 1 ;
}
if ( ! res && ( gosub_result = pbx_builtin_getvar_helper ( peer , "GOSUB_RESULT" ))) {
char * gosub_transfer_dest ;
if ( ! strcasecmp ( gosub_result , "BUSY" )) {
ast_copy_string ( pa . status , gosub_result , sizeof ( pa . status ));
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_set_flag64 ( peerflags , OPT_GO_ON );
2007-06-19 23:36:34 +00:00
res = - 1 ;
} else if ( ! strcasecmp ( gosub_result , "CONGESTION" ) || ! strcasecmp ( gosub_result , "CHANUNAVAIL" )) {
ast_copy_string ( pa . status , gosub_result , sizeof ( pa . status ));
2008-02-09 11:27:10 +00:00
ast_set_flag64 ( peerflags , OPT_GO_ON );
2007-06-19 23:36:34 +00:00
res = - 1 ;
} else if ( ! strcasecmp ( gosub_result , "CONTINUE" )) {
2008-02-09 11:27:10 +00:00
/* hangup peer and keep chan alive assuming the macro has changed
the context / exten / priority or perhaps
2007-06-19 23:36:34 +00:00
the next priority in the current exten is desired.
*/
2008-02-09 11:27:10 +00:00
ast_set_flag64 ( peerflags , OPT_GO_ON );
2007-06-19 23:36:34 +00:00
res = - 1 ;
} else if ( ! strcasecmp ( gosub_result , "ABORT" )) {
/* Hangup both ends unless the caller has the g flag */
res = - 1 ;
} else if ( ! strncasecmp ( gosub_result , "GOTO:" , 5 ) && ( gosub_transfer_dest = ast_strdupa ( gosub_result + 5 ))) {
res = - 1 ;
/* perform a transfer to a new extension */
if ( strchr ( gosub_transfer_dest , '^' )) { /* context^exten^priority*/
replace_macro_delimiter ( gosub_transfer_dest );
if ( ! ast_parseable_goto ( chan , gosub_transfer_dest ))
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
ast_set_flag64 ( peerflags , OPT_GO_ON );
2007-06-19 23:36:34 +00:00
}
}
}
}
2004-05-07 21:14:55 +00:00
if ( ! res ) {
if ( calldurationlimit > 0 ) {
2007-06-20 19:30:31 +00:00
peer -> whentohangup = time ( NULL ) + calldurationlimit ;
2004-05-07 21:14:55 +00:00
}
2008-02-09 11:27:10 +00:00
if ( ! ast_strlen_zero ( dtmfcalled )) {
2008-02-05 23:00:15 +00:00
ast_verb ( 3 , "Sending DTMF '%s' to the called party. \n " , dtmfcalled );
2007-12-12 20:05:13 +00:00
res = ast_dtmf_stream ( peer , chan , dtmfcalled , 250 , 0 );
2005-04-11 02:46:25 +00:00
}
2005-10-26 19:48:14 +00:00
if ( ! ast_strlen_zero ( dtmfcalling )) {
2008-02-05 23:00:15 +00:00
ast_verb ( 3 , "Sending DTMF '%s' to the calling party. \n " , dtmfcalling );
2007-12-12 20:05:13 +00:00
res = ast_dtmf_stream ( chan , peer , dtmfcalling , 250 , 0 );
2005-04-11 02:46:25 +00:00
}
2004-05-07 20:39:14 +00:00
}
2008-02-09 11:27:10 +00:00
if ( res ) { /* some error */
2006-11-04 01:16:20 +00:00
res = - 1 ;
end_time = time ( NULL );
} else {
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLEE_TRANSFER ))
2005-01-10 14:46:59 +00:00
ast_set_flag ( & ( config . features_callee ), AST_FEATURE_REDIRECT );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLER_TRANSFER ))
2005-01-10 14:46:59 +00:00
ast_set_flag ( & ( config . features_caller ), AST_FEATURE_REDIRECT );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLEE_HANGUP ))
2005-01-10 14:46:59 +00:00
ast_set_flag ( & ( config . features_callee ), AST_FEATURE_DISCONNECT );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLER_HANGUP ))
2005-01-10 14:46:59 +00:00
ast_set_flag ( & ( config . features_caller ), AST_FEATURE_DISCONNECT );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLEE_MONITOR ))
2005-01-10 14:46:59 +00:00
ast_set_flag ( & ( config . features_callee ), AST_FEATURE_AUTOMON );
2008-02-09 11:27:10 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLER_MONITOR ))
2005-01-10 14:46:59 +00:00
ast_set_flag ( & ( config . features_caller ), AST_FEATURE_AUTOMON );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLEE_PARK ))
2006-05-22 16:43:43 +00:00
ast_set_flag ( & ( config . features_callee ), AST_FEATURE_PARKCALL );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLER_PARK ))
2006-05-22 16:43:43 +00:00
ast_set_flag ( & ( config . features_caller ), AST_FEATURE_PARKCALL );
2007-11-30 21:19:57 +00:00
if ( ast_test_flag64 ( peerflags , OPT_CALLEE_MIXMONITOR ))
ast_set_flag ( & ( config . features_callee ), AST_FEATURE_AUTOMIXMON );
if ( ast_test_flag64 ( peerflags , OPT_CALLER_MIXMONITOR ))
ast_set_flag ( & ( config . features_caller ), AST_FEATURE_AUTOMIXMON );
2005-01-18 03:12:53 +00:00
2004-06-21 18:28:35 +00:00
if ( moh ) {
moh = 0 ;
ast_moh_stop ( chan );
} else if ( sentringing ) {
sentringing = 0 ;
ast_indicate ( chan , - 1 );
}
2004-07-07 16:02:13 +00:00
/* Be sure no generators are left on it */
ast_deactivate_generator ( chan );
/* Make sure channels are compatible */
res = ast_channel_make_compatible ( chan , peer );
if ( res < 0 ) {
ast_log ( LOG_WARNING , "Had to drop call because I couldn't make %s compatible with %s \n " , chan -> name , peer -> name );
ast_hangup ( peer );
2006-04-19 16:54:04 +00:00
res = - 1 ;
goto done ;
2004-07-07 16:02:13 +00:00
}
2007-12-12 20:05:13 +00:00
if ( opermode && ! strncmp ( chan -> name , "Zap" , 3 ) && ! strncmp ( peer -> name , "Zap" , 3 )) {
/* what's this special handling for Zap <-> Zap ?
* A: Zap to Zap calls are natively bridged at the kernel driver
* level, so we need to ensure that this mode gets propagated
* all the way down. */
2006-04-22 11:30:06 +00:00
struct oprmode oprmode ;
oprmode . peer = peer ;
oprmode . mode = opermode ;
2007-12-14 14:48:38 +00:00
ast_channel_setoption ( chan , AST_OPTION_OPRMODE , & oprmode , sizeof ( oprmode ), 0 );
2006-04-22 11:30:06 +00:00
}
2007-12-12 20:05:13 +00:00
res = ast_bridge_call ( chan , peer , & config );
2006-11-04 01:16:20 +00:00
end_time = time ( NULL );
snprintf ( toast , sizeof ( toast ), "%ld" , ( long )( end_time - answer_time ));
pbx_builtin_setvar_helper ( chan , "ANSWEREDTIME" , toast );
2006-04-19 16:19:52 +00:00
}
2006-11-04 01:16:20 +00:00
snprintf ( toast , sizeof ( toast ), "%ld" , ( long )( end_time - start_time ));
pbx_builtin_setvar_helper ( chan , "DIALEDTIME" , toast );
2008-02-09 11:27:10 +00:00
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_PEER_H )) {
2008-02-09 11:27:10 +00:00
ast_log ( LOG_NOTICE , "PEER context: %s; PEER exten: %s; PEER priority: %d \n " ,
peer -> context , peer -> exten , peer -> priority );
2007-07-17 19:40:29 +00:00
}
2008-02-09 11:27:10 +00:00
2007-07-17 19:40:29 +00:00
strcpy ( peer -> context , chan -> context );
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & opts , OPT_PEER_H ) && ast_exists_extension ( peer , peer -> context , "h" , 1 , peer -> cid . cid_num )) {
2007-07-27 15:46:20 +00:00
int autoloopflag ;
This commits the performance mods that give the priority processing engine in the pbx, a 25-30% speed boost. The two updates used, are, first, to merge the ast_exists_extension() and the ast_spawn_extension() where they are called sequentially in a loop in the code, into a slightly upgraded version of ast_spawn_extension(), with a few extra args; and, second, I modified the substitute_variables_helper_full, so it zeroes out the byte after the evaluated string instead of demanding you pre-zero the buffer; I also went thru the code and removed the code that zeroed this buffer before every call to the substitute_variables_helper_full. The first fix provides about a 9% speedup, and the second the rest. These figures come from the 'PIPS' benchmark I describe in blogs, conf. reports, etc.
2007-11-01 22:26:51 +00:00
int found ;
2007-07-17 19:40:29 +00:00
strcpy ( peer -> exten , "h" );
peer -> priority = 1 ;
2008-02-09 11:27:10 +00:00
autoloopflag = ast_test_flag ( peer , AST_FLAG_IN_AUTOLOOP ); /* save value to restore at the end */
2007-07-27 15:46:20 +00:00
ast_set_flag ( peer , AST_FLAG_IN_AUTOLOOP );
2008-02-09 11:27:10 +00:00
while (( res = ast_spawn_extension ( peer , peer -> context , peer -> exten , peer -> priority , peer -> cid . cid_num , & found , 1 )))
2007-07-17 19:40:29 +00:00
peer -> priority ++ ;
2008-02-09 11:27:10 +00:00
This commits the performance mods that give the priority processing engine in the pbx, a 25-30% speed boost. The two updates used, are, first, to merge the ast_exists_extension() and the ast_spawn_extension() where they are called sequentially in a loop in the code, into a slightly upgraded version of ast_spawn_extension(), with a few extra args; and, second, I modified the substitute_variables_helper_full, so it zeroes out the byte after the evaluated string instead of demanding you pre-zero the buffer; I also went thru the code and removed the code that zeroed this buffer before every call to the substitute_variables_helper_full. The first fix provides about a 9% speedup, and the second the rest. These figures come from the 'PIPS' benchmark I describe in blogs, conf. reports, etc.
2007-11-01 22:26:51 +00:00
if ( found && res ) {
/* Something bad happened, or a hangup has been requested. */
ast_debug ( 1 , "Spawn extension (%s,%s,%d) exited non-zero on '%s' \n " , peer -> context , peer -> exten , peer -> priority , peer -> name );
ast_verb ( 2 , "Spawn extension (%s, %s, %d) exited non-zero on '%s' \n " , peer -> context , peer -> exten , peer -> priority , peer -> name );
}
2007-07-27 15:46:20 +00:00
ast_set2_flag ( peer , autoloopflag , AST_FLAG_IN_AUTOLOOP ); /* set it back the way it was */
2007-07-17 19:40:29 +00:00
}
2004-05-22 23:17:33 +00:00
if ( res != AST_PBX_NO_HANGUP_PEER ) {
2007-08-01 15:39:54 +00:00
if ( ! ast_check_hangup ( chan ))
2004-05-22 23:17:33 +00:00
chan -> hangupcause = peer -> hangupcause ;
2004-05-07 21:14:55 +00:00
ast_hangup ( peer );
2004-05-22 23:17:33 +00:00
}
2008-02-09 11:27:10 +00:00
}
1999-12-04 21:35:07 +00:00
out :
2004-06-21 18:28:35 +00:00
if ( moh ) {
moh = 0 ;
ast_moh_stop ( chan );
} else if ( sentringing ) {
sentringing = 0 ;
ast_indicate ( chan , - 1 );
}
2006-09-21 19:27:26 +00:00
ast_channel_early_bridge ( chan , NULL );
2008-02-09 11:27:10 +00:00
hanguptree ( outgoing , NULL , 0 ); /* In this case, there's no answer anywhere */
2006-11-04 11:00:49 +00:00
pbx_builtin_setvar_helper ( chan , "DIALSTATUS" , pa . status );
senddialendevent ( chan , pa . status );
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , "Exiting with DIALSTATUS=%s. \n " , pa . status );
2008-02-09 11:27:10 +00:00
2007-08-01 15:39:54 +00:00
if (( ast_test_flag64 ( peerflags , OPT_GO_ON )) && ! ast_check_hangup ( chan ) && ( res != AST_PBX_KEEPALIVE )) {
2007-06-07 14:23:21 +00:00
if ( calldurationlimit )
chan -> whentohangup = 0 ;
2006-01-17 18:54:56 +00:00
res = 0 ;
2007-06-07 14:23:21 +00:00
}
2006-04-19 14:02:49 +00:00
done :
1999-12-04 21:35:07 +00:00
return res ;
}
2005-01-18 03:12:53 +00:00
static int dial_exec ( struct ast_channel * chan , void * data )
{
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
struct ast_flags64 peerflags ;
2007-01-10 04:56:48 +00:00
2005-01-18 03:12:53 +00:00
memset ( & peerflags , 0 , sizeof ( peerflags ));
2007-01-10 04:56:48 +00:00
2007-02-15 16:24:13 +00:00
return dial_exec_full ( chan , data , & peerflags , NULL );
2005-01-18 03:12:53 +00:00
}
static int retrydial_exec ( struct ast_channel * chan , void * data )
{
2007-07-23 19:51:41 +00:00
char * parse ;
2005-12-20 17:52:31 +00:00
const char * context = NULL ;
2006-04-19 14:02:49 +00:00
int sleep = 0 , loops = 0 , res = - 1 ;
2007-07-23 19:51:41 +00:00
struct ast_flags64 peerflags = { 0 , };
AST_DECLARE_APP_ARGS ( args ,
AST_APP_ARG ( announce );
AST_APP_ARG ( sleep );
AST_APP_ARG ( retries );
AST_APP_ARG ( dialdata );
);
2005-10-26 19:48:14 +00:00
if ( ast_strlen_zero ( data )) {
2005-10-19 18:19:02 +00:00
ast_log ( LOG_WARNING , "RetryDial requires an argument! \n " );
return - 1 ;
2008-02-09 11:27:10 +00:00
}
2005-01-18 03:12:53 +00:00
2007-07-23 19:51:41 +00:00
parse = ast_strdupa ( data );
AST_STANDARD_APP_ARGS ( args , parse );
2005-10-19 18:19:02 +00:00
2008-02-09 11:27:10 +00:00
if (( sleep = atoi ( args . sleep )))
2007-07-23 19:51:41 +00:00
sleep *= 1000 ;
loops = atoi ( args . retries );
if ( ! args . dialdata ) {
ast_log ( LOG_ERROR , "%s requires a 4th argument (dialdata) \n " , rapp );
2006-04-19 14:02:49 +00:00
goto done ;
2005-01-18 03:12:53 +00:00
}
2008-02-09 11:27:10 +00:00
2005-01-18 03:12:53 +00:00
if ( sleep < 1000 )
sleep = 10000 ;
2006-04-19 14:02:49 +00:00
2005-01-18 03:12:53 +00:00
if ( ! loops )
2008-02-09 11:27:10 +00:00
loops = - 1 ; /* run forever */
2005-01-18 03:12:53 +00:00
context = pbx_builtin_getvar_helper ( chan , "EXITCONTEXT" );
2006-04-19 14:02:49 +00:00
res = 0 ;
2005-01-18 03:12:53 +00:00
while ( loops ) {
2007-02-15 16:24:13 +00:00
int continue_exec ;
2005-01-18 03:12:53 +00:00
chan -> data = "Retrying" ;
if ( ast_test_flag ( chan , AST_FLAG_MOH ))
ast_moh_stop ( chan );
2007-07-23 19:51:41 +00:00
res = dial_exec_full ( chan , args . dialdata , & peerflags , & continue_exec );
2007-02-15 16:24:13 +00:00
if ( continue_exec )
2007-01-10 04:56:48 +00:00
break ;
2007-07-16 18:18:19 +00:00
2007-02-15 16:24:13 +00:00
if ( res == 0 ) {
After some study, thought, comparing, etc. I've backed out the previous universal mod to make ast_flags a 64 bit thing. Instead, I added a 64-bit version of ast_flags (ast_flags64), and 64-bit versions of the test-flag, set-flag, etc. macros, and an app_parse_options64 routine, and I use these in app_dial alone, to eliminate the 30-option limit it had grown to meet. There is room now for 32 more options and flags. I was heavily tempted to implement some of the other ideas that were presented, but this solution does not intro any new versions of dial, doesn't have a different API, has a minimal/zero impact on code outside of dial, and doesn't seriously (I hope) affect the code structure of dial. It's the best I can think of right now. My goal was NOT to rewrite dial. I leave that to a future, coordinated effort.
2007-07-19 23:24:27 +00:00
if ( ast_test_flag64 ( & peerflags , OPT_DTMF_EXIT )) {
2007-07-23 19:51:41 +00:00
if ( ! ast_strlen_zero ( args . announce )) {
if ( ast_fileexists ( args . announce , NULL , chan -> language ) > 0 ) {
2008-02-09 11:27:10 +00:00
if ( ! ( res = ast_streamfile ( chan , args . announce , chan -> language )))
2007-07-16 18:18:19 +00:00
ast_waitstream ( chan , AST_DIGIT_ANY );
} else
2007-07-23 19:51:41 +00:00
ast_log ( LOG_WARNING , "Announce file \" %s \" specified in Retrydial does not exist \n " , args . announce );
2007-07-16 18:18:19 +00:00
}
2005-01-20 22:59:50 +00:00
if ( ! res && sleep ) {
2005-01-18 03:12:53 +00:00
if ( ! ast_test_flag ( chan , AST_FLAG_MOH ))
2006-07-19 20:44:39 +00:00
ast_moh_start ( chan , NULL , NULL );
2005-01-18 03:12:53 +00:00
res = ast_waitfordigit ( chan , sleep );
}
} else {
2007-07-23 19:51:41 +00:00
if ( ! ast_strlen_zero ( args . announce )) {
if ( ast_fileexists ( args . announce , NULL , chan -> language ) > 0 ) {
if ( ! ( res = ast_streamfile ( chan , args . announce , chan -> language )))
2007-07-16 18:18:19 +00:00
res = ast_waitstream ( chan , "" );
} else
2007-07-23 19:51:41 +00:00
ast_log ( LOG_WARNING , "Announce file \" %s \" specified in Retrydial does not exist \n " , args . announce );
2007-07-16 18:18:19 +00:00
}
2005-01-20 22:59:50 +00:00
if ( sleep ) {
if ( ! ast_test_flag ( chan , AST_FLAG_MOH ))
2006-07-19 20:44:39 +00:00
ast_moh_start ( chan , NULL , NULL );
2007-07-16 18:18:19 +00:00
if ( ! res )
2005-06-01 18:02:46 +00:00
res = ast_waitfordigit ( chan , sleep );
2005-01-20 22:59:50 +00:00
}
2005-01-18 03:12:53 +00:00
}
}
if ( res < 0 )
break ;
else if ( res > 0 ) { /* Trying to send the call elsewhere (1 digit ext) */
2005-04-29 15:04:26 +00:00
if ( onedigit_goto ( chan , context , ( char ) res , 1 )) {
2005-01-18 03:12:53 +00:00
res = 0 ;
break ;
}
}
loops -- ;
}
2006-04-19 14:02:49 +00:00
if ( loops == 0 )
res = 0 ;
2007-01-10 04:56:48 +00:00
else if ( res == 1 )
res = 0 ;
2005-01-18 03:12:53 +00:00
if ( ast_test_flag ( chan , AST_FLAG_MOH ))
ast_moh_stop ( chan );
2007-01-10 04:56:48 +00:00
done :
2006-04-19 14:02:49 +00:00
return res ;
2005-01-18 03:12:53 +00:00
}
2006-08-21 02:11:39 +00:00
static int unload_module ( void )
1999-12-04 21:35:07 +00:00
{
2005-10-18 22:52:21 +00:00
int res ;
2007-06-20 17:35:08 +00:00
struct ast_context * con ;
2005-10-18 22:52:21 +00:00
res = ast_unregister_application ( app );
res |= ast_unregister_application ( rapp );
2008-02-09 11:27:10 +00:00
if (( con = ast_context_find ( "app_dial_gosub_virtual_context" ))) {
2007-06-20 17:35:08 +00:00
ast_context_remove_extension2 ( con , "s" , 1 , NULL );
closes issue #11285 , where an unload of a module that creates a dialplan context, causes a crash when you do a 'dialplan show' of that context. This is because the registrar string is defined in the module, and the stale pointer is traversed. The reporter offered a patch that would always strdup the registrar string, which is practical, but I preferred to destroy the created contexts in each module where one is created. That seemed more symmetric. There were only 6 place in asterisk where this is done: chan_sip, chan_iax2, chan_skinny, res_features, app_dial, and app_queue. The two apps destroyed the context, but left the contexts. All is fixed now and unloads should be dialplan friendly.
2007-11-21 23:54:12 +00:00
ast_context_destroy ( con , "app_dial" ); /* leave nothing behind */
}
2008-02-09 11:27:10 +00:00
2005-10-18 22:52:21 +00:00
return res ;
1999-12-04 21:35:07 +00:00
}
2006-08-21 02:11:39 +00:00
static int load_module ( void )
1999-12-04 21:35:07 +00:00
{
2000-03-26 01:59:06 +00:00
int res ;
2007-06-20 17:35:08 +00:00
struct ast_context * con ;
2008-03-07 18:57:57 +00:00
con = ast_context_find_or_create ( NULL , NULL , "app_dial_gosub_virtual_context" , "app_dial" );
2007-06-20 17:35:08 +00:00
if ( ! con )
ast_log ( LOG_ERROR , "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create \n " );
else
2007-09-17 18:57:56 +00:00
ast_add_extension2 ( con , 1 , "s" , 1 , NULL , NULL , "KeepAlive" , ast_strdup ( "" ), ast_free_ptr , "app_dial" );
2005-10-18 22:52:21 +00:00
res = ast_register_application ( app , dial_exec , synopsis , descrip );
res |= ast_register_application ( rapp , retrydial_exec , rsynopsis , rdescrip );
2008-02-09 11:27:10 +00:00
2000-03-26 01:59:06 +00:00
return res ;
1999-12-04 21:35:07 +00:00
}
2006-08-21 02:11:39 +00:00
AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY , "Dialing Application" );