Fri Sep 25 19:28:03 2009

Asterisk developer's documentation


app_dial.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * Copyright (C) 2004, Junghanns.NET GmbH
00015  *
00016  * Klaus-Peter Junghanns <kpj@junghanns.net>
00017  *
00018  * This program is free software, distributed under the terms of
00019  * the GNU General Public License Version 2. See the LICENSE file
00020  * at the top of the source tree.
00021  */
00022 
00023 /*! \file
00024  *
00025  * \brief dial() & retrydial() - Trivial application to dial a channel and send an URL on answer
00026  *
00027  * \author Mark Spencer <markster@digium.com>
00028  * 
00029  * \ingroup applications
00030  */
00031 
00032 #include "asterisk.h"
00033 
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 91783 $")
00035 
00036 #include <stdlib.h>
00037 #include <errno.h>
00038 #include <unistd.h>
00039 #include <string.h>
00040 #include <stdlib.h>
00041 #include <stdio.h>
00042 #include <sys/time.h>
00043 #include <sys/signal.h>
00044 #include <sys/stat.h>
00045 #include <netinet/in.h>
00046 
00047 #include "asterisk/lock.h"
00048 #include "asterisk/file.h"
00049 #include "asterisk/logger.h"
00050 #include "asterisk/channel.h"
00051 #include "asterisk/pbx.h"
00052 #include "asterisk/options.h"
00053 #include "asterisk/module.h"
00054 #include "asterisk/translate.h"
00055 #include "asterisk/say.h"
00056 #include "asterisk/config.h"
00057 #include "asterisk/features.h"
00058 #include "asterisk/musiconhold.h"
00059 #include "asterisk/callerid.h"
00060 #include "asterisk/utils.h"
00061 #include "asterisk/app.h"
00062 #include "asterisk/causes.h"
00063 #include "asterisk/rtp.h"
00064 #include "asterisk/cdr.h"
00065 #include "asterisk/manager.h"
00066 #include "asterisk/privacy.h"
00067 #include "asterisk/stringfields.h"
00068 #include "asterisk/global_datastores.h"
00069 #include "asterisk/transcap.h"
00070 
00071 static char *app = "Dial";
00072 
00073 static char *synopsis = "Place a call and connect to the current channel";
00074 
00075 static char *descrip =
00076 "  Dial(Technology/resource[&Tech2/resource2...][|timeout][|options][|URL]):\n"
00077 "This application will place calls to one or more specified channels. As soon\n"
00078 "as one of the requested channels answers, the originating channel will be\n"
00079 "answered, if it has not already been answered. These two channels will then\n"
00080 "be active in a bridged call. All other channels that were requested will then\n"
00081 "be hung up.\n"
00082 "  Unless there is a timeout specified, the Dial application will wait\n"
00083 "indefinitely until one of the called channels answers, the user hangs up, or\n"
00084 "if all of the called channels are busy or unavailable. Dialplan executing will\n"
00085 "continue if no requested channels can be called, or if the timeout expires.\n\n"
00086 "  This application sets the following channel variables upon completion:\n"
00087 "    DIALEDTIME   - This is the time from dialing a channel until when it\n"
00088 "                   is disconnected.\n" 
00089 "    ANSWEREDTIME - This is the amount of time for actual call.\n"
00090 "    DIALSTATUS   - This is the status of the call:\n"
00091 "                   CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n" 
00092 "                   DONTCALL | TORTURE | INVALIDARGS\n"
00093 "  For the Privacy and Screening Modes, the DIALSTATUS variable will be set to\n"
00094 "DONTCALL if the called party chooses to send the calling party to the 'Go Away'\n"
00095 "script. The DIALSTATUS variable will be set to TORTURE if the called party\n"
00096 "wants to send the caller to the 'torture' script.\n"
00097 "  This application will report normal termination if the originating channel\n"
00098 "hangs up, or if the call is bridged and either of the parties in the bridge\n"
00099 "ends the call.\n"
00100 "  The optional URL will be sent to the called party if the channel supports it.\n"
00101 "  If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
00102 "application will be put into that group (as in Set(GROUP()=...).\n"
00103 "  If the OUTBOUND_GROUP_ONCE variable is set, all peer channels created by this\n"
00104 "application will be put into that group (as in Set(GROUP()=...). Unlike OUTBOUND_GROUP,\n"
00105 "however, the variable will be unset after use.\n\n"
00106 "  Options:\n"
00107 "    A(x) - Play an announcement to the called party, using 'x' as the file.\n"
00108 "    C    - Reset the CDR for this call.\n"
00109 "    d    - Allow the calling user to dial a 1 digit extension while waiting for\n"
00110 "           a call to be answered. Exit to that extension if it exists in the\n"
00111 "           current context, or the context defined in the EXITCONTEXT variable,\n"
00112 "           if it exists.\n"
00113 "    D([called][:calling]) - Send the specified DTMF strings *after* the called\n"
00114 "           party has answered, but before the call gets bridged. The 'called'\n"
00115 "           DTMF string is sent to the called party, and the 'calling' DTMF\n"
00116 "           string is sent to the calling party. Both parameters can be used\n"
00117 "           alone.\n"   
00118 "    f    - Force the callerid of the *calling* channel to be set as the\n"
00119 "           extension associated with the channel using a dialplan 'hint'.\n"
00120 "           For example, some PSTNs do not allow CallerID to be set to anything\n"
00121 "           other than the number assigned to the caller.\n"
00122 "    g    - Proceed with dialplan execution at the current extension if the\n"
00123 "           destination channel hangs up.\n"
00124 "    G(context^exten^pri) - If the call is answered, transfer the calling party to\n"
00125 "           the specified priority and the called party to the specified priority+1.\n"
00126 "           Optionally, an extension, or extension and context may be specified. \n"
00127 "           Otherwise, the current extension is used. You cannot use any additional\n"
00128 "           action post answer options in conjunction with this option.\n" 
00129 "    h    - Allow the called party to hang up by sending the '*' DTMF digit.\n"
00130 "    H    - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
00131 "    i    - Asterisk will ignore any forwarding requests it may receive on this\n"
00132 "           dial attempt.\n"
00133 "    j    - Jump to priority n+101 if the called party was busy.\n"
00134 "           Jump to priority n+201 if all of the requested channels were busy.\n"
00135 "    k    - Allow the called party to enable parking of the call by sending\n"
00136 "           the DTMF sequence defined for call parking in features.conf.\n"
00137 "    K    - Allow the calling party to enable parking of the call by sending\n"
00138 "           the DTMF sequence defined for call parking in features.conf.\n"
00139 "    L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
00140 "           left. Repeat the warning every 'z' ms. The following special\n"
00141 "           variables can be used with this option:\n"
00142 "           * LIMIT_PLAYAUDIO_CALLER   yes|no (default yes)\n"
00143 "                                      Play sounds to the caller.\n"
00144 "           * LIMIT_PLAYAUDIO_CALLEE   yes|no\n"
00145 "                                      Play sounds to the callee.\n"
00146 "           * LIMIT_TIMEOUT_FILE       File to play when time is up.\n"
00147 "           * LIMIT_CONNECT_FILE       File to play when call begins.\n"
00148 "           * LIMIT_WARNING_FILE       File to play as warning if 'y' is defined.\n"
00149 "                                      The default is to say the time remaining.\n"
00150 "    m([class]) - Provide hold music to the calling party until a requested\n"
00151 "           channel answers. A specific MusicOnHold class can be\n"
00152 "           specified.\n"
00153 "    M(x[^arg]) - Execute the Macro for the *called* channel before connecting\n"
00154 "           to the calling channel. Arguments can be specified to the Macro\n"
00155 "           using '^' as a delimeter. The Macro can set the variable\n"
00156 "           MACRO_RESULT to specify the following actions after the Macro is\n" 
00157 "           finished executing.\n"
00158 "           * ABORT        Hangup both legs of the call.\n"
00159 "           * CONGESTION   Behave as if line congestion was encountered.\n"
00160 "           * BUSY         Behave as if a busy signal was encountered. This will also\n"
00161 "                          have the application jump to priority n+101 if the\n"
00162 "                          'j' option is set.\n"
00163 "           * CONTINUE     Hangup the called party and allow the calling party\n"
00164 "                          to continue dialplan execution at the next priority.\n"
00165 "           * GOTO:<context>^<exten>^<priority> - Transfer the call to the\n"
00166 "                          specified priority. Optionally, an extension, or\n"
00167 "                          extension and priority can be specified.\n"
00168 "           You cannot use any additional action post answer options in conjunction\n"
00169 "           with this option. Also, pbx services are not run on the peer (called) channel,\n"
00170 "           so you will not be able to set timeouts via the TIMEOUT() function in this macro.\n"
00171 "    n    - This option is a modifier for the screen/privacy mode. It specifies\n"
00172 "           that no introductions are to be saved in the priv-callerintros\n"
00173 "           directory.\n"
00174 "    N    - This option is a modifier for the screen/privacy mode. It specifies\n"
00175 "           that if callerID is present, do not screen the call.\n"
00176 "    o    - Specify that the CallerID that was present on the *calling* channel\n"
00177 "           be set as the CallerID on the *called* channel. This was the\n"
00178 "           behavior of Asterisk 1.0 and earlier.\n"
00179 "    O([x]) - \"Operator Services\" mode (Zaptel channel to Zaptel channel\n"
00180 "             only, if specified on non-Zaptel interface, it will be ignored).\n"
00181 "             When the destination answers (presumably an operator services\n"
00182 "             station), the originator no longer has control of their line.\n"
00183 "             They may hang up, but the switch will not release their line\n"
00184 "             until the destination party hangs up (the operator). Specified\n"
00185 "             without an arg, or with 1 as an arg, the originator hanging up\n"
00186 "             will cause the phone to ring back immediately. With a 2 specified,\n"
00187 "             when the \"operator\" flashes the trunk, it will ring their phone\n"
00188 "             back.\n"
00189 "    p    - This option enables screening mode. This is basically Privacy mode\n"
00190 "           without memory.\n"
00191 "    P([x]) - Enable privacy mode. Use 'x' as the family/key in the database if\n"
00192 "           it is provided. The current extension is used if a database\n"
00193 "           family/key is not specified.\n"
00194 "    r    - Indicate ringing to the calling party. Pass no audio to the calling\n"
00195 "           party until the called channel has answered.\n"
00196 "    R     - indicate ringing to the calling party when the called party indicates\n"
00197 "            ringing, pass no audio until answered.\n"
00198 "    S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
00199 "           answered the call.\n"
00200 "    c    - callback initiation, ring once and hangup.\n"
00201 "    t    - Allow the called party to transfer the calling party by sending the\n"
00202 "           DTMF sequence defined in features.conf.\n"
00203 "    T    - Allow the calling party to transfer the called party by sending the\n"
00204 "           DTMF sequence defined in features.conf.\n"
00205 "    w    - Allow the called party to enable recording of the call by sending\n"
00206 "           the DTMF sequence defined for one-touch recording in features.conf.\n"
00207 "    W    - Allow the calling party to enable recording of the call by sending\n"
00208 "           the DTMF sequence defined for one-touch recording in features.conf.\n";
00209 
00210 /* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
00211 static char *rapp = "RetryDial";
00212 static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
00213 static char *rdescrip =
00214 "  RetryDial(announce|sleep|retries|dialargs): This application will attempt to\n"
00215 "place a call using the normal Dial application. If no channel can be reached,\n"
00216 "the 'announce' file will be played. Then, it will wait 'sleep' number of\n"
00217 "seconds before retying the call. After 'retires' number of attempts, the\n"
00218 "calling channel will continue at the next priority in the dialplan. If the\n"
00219 "'retries' setting is set to 0, this application will retry endlessly.\n"
00220 "  While waiting to retry a call, a 1 digit extension may be dialed. If that\n"
00221 "extension exists in either the context defined in ${EXITCONTEXT} or the current\n"
00222 "one, The call will jump to that extension immediately.\n"
00223 "  The 'dialargs' are specified in the same format that arguments are provided\n"
00224 "to the Dial application.\n";
00225 
00226 enum {
00227    OPT_ANNOUNCE =    (1 << 0),
00228    OPT_RESETCDR =    (1 << 1),
00229    OPT_DTMF_EXIT =      (1 << 2),
00230    OPT_SENDDTMF =    (1 << 3),
00231    OPT_FORCECLID =      (1 << 4),
00232    OPT_GO_ON =    (1 << 5),
00233    OPT_CALLEE_HANGUP =  (1 << 6),
00234    OPT_CALLER_HANGUP =  (1 << 7),
00235    OPT_PRIORITY_JUMP =  (1 << 8),
00236    OPT_DURATION_LIMIT = (1 << 9),
00237    OPT_MUSICBACK =      (1 << 10),
00238    OPT_CALLEE_MACRO =   (1 << 11),
00239    OPT_SCREEN_NOINTRO = (1 << 12),
00240    OPT_SCREEN_NOCLID =  (1 << 13),
00241    OPT_ORIGINAL_CLID =  (1 << 14),
00242    OPT_SCREENING =      (1 << 15),
00243    OPT_PRIVACY =     (1 << 16),
00244    OPT_RINGBACK =    (1 << 17),
00245    OPT_DURATION_STOP =  (1 << 18),
00246    OPT_CALLEE_TRANSFER =   (1 << 19),
00247    OPT_CALLER_TRANSFER =   (1 << 20),
00248    OPT_CALLEE_MONITOR = (1 << 21),
00249    OPT_CALLER_MONITOR = (1 << 22),
00250    OPT_GOTO =     (1 << 23),
00251    OPT_OPERMODE =       (1 << 24),
00252    OPT_CALLEE_PARK = (1 << 25),
00253    OPT_CALLER_PARK = (1 << 26),
00254    OPT_IGNORE_FORWARDING = (1 << 27),
00255    OPT_NOINBAND =       (1 << 28),
00256    OPT_CALLBACK_INIT =  (1 << 29),
00257 } dial_exec_option_flags;
00258 
00259 #define DIAL_STILLGOING       (1 << 30)
00260 #define DIAL_NOFORWARDHTML    (1 << 31)
00261 
00262 enum {
00263    OPT_ARG_ANNOUNCE = 0,
00264    OPT_ARG_SENDDTMF,
00265    OPT_ARG_GOTO,
00266    OPT_ARG_DURATION_LIMIT,
00267    OPT_ARG_MUSICBACK,
00268    OPT_ARG_CALLEE_MACRO,
00269    OPT_ARG_PRIVACY,
00270    OPT_ARG_DURATION_STOP,
00271    OPT_ARG_OPERMODE,
00272    /* note: this entry _MUST_ be the last one in the enum */
00273    OPT_ARG_ARRAY_SIZE,
00274 } dial_exec_option_args;
00275 
00276 AST_APP_OPTIONS(dial_exec_options, {
00277    AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
00278    AST_APP_OPTION('C', OPT_RESETCDR),
00279    AST_APP_OPTION('d', OPT_DTMF_EXIT),
00280    AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF),
00281    AST_APP_OPTION('f', OPT_FORCECLID),
00282    AST_APP_OPTION('g', OPT_GO_ON),
00283    AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO),
00284    AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
00285    AST_APP_OPTION('H', OPT_CALLER_HANGUP),
00286    AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
00287    AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
00288    AST_APP_OPTION('k', OPT_CALLEE_PARK),
00289    AST_APP_OPTION('K', OPT_CALLER_PARK),
00290    AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
00291    AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
00292    AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
00293    AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
00294    AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
00295    AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
00296    AST_APP_OPTION_ARG('O', OPT_OPERMODE,OPT_ARG_OPERMODE),
00297    AST_APP_OPTION('p', OPT_SCREENING),
00298    AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
00299    AST_APP_OPTION('r', OPT_RINGBACK),
00300    AST_APP_OPTION('R', OPT_NOINBAND),
00301    AST_APP_OPTION('c', OPT_CALLBACK_INIT),
00302    AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
00303    AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
00304    AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
00305    AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
00306    AST_APP_OPTION('W', OPT_CALLER_MONITOR),
00307 });
00308 
00309 #define CAN_EARLY_BRIDGE(flags) (!ast_test_flag(flags, OPT_CALLEE_HANGUP | \
00310    OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \
00311    OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK | OPT_CALLER_PARK))
00312 
00313 /* We define a custom "local user" structure because we
00314    use it not only for keeping track of what is in use but
00315    also for keeping track of who we're dialing. */
00316 
00317 struct dial_localuser {
00318    struct ast_channel *chan;
00319    unsigned int flags;
00320    struct dial_localuser *next;
00321 };
00322 
00323 
00324 static void hanguptree(struct dial_localuser *outgoing, struct ast_channel *exception)
00325 {
00326    /* Hang up a tree of stuff */
00327    struct dial_localuser *oo;
00328    while (outgoing) {
00329       /* Hangup any existing lines we have open */
00330       if (outgoing->chan && (outgoing->chan != exception))
00331          ast_hangup(outgoing->chan);
00332       oo = outgoing;
00333       outgoing=outgoing->next;
00334       free(oo);
00335    }
00336 }
00337 
00338 #define AST_MAX_WATCHERS 256
00339 
00340 #define HANDLE_CAUSE(cause, chan) do { \
00341    switch(cause) { \
00342    case AST_CAUSE_BUSY: \
00343       if (chan->cdr) \
00344          ast_cdr_busy(chan->cdr); \
00345       numbusy++; \
00346       break; \
00347    case AST_CAUSE_CONGESTION: \
00348       if (chan->cdr) \
00349          ast_cdr_failed(chan->cdr); \
00350       numcongestion++; \
00351       break; \
00352    case AST_CAUSE_UNREGISTERED: \
00353       if (chan->cdr) \
00354          ast_cdr_failed(chan->cdr); \
00355       numnochan++; \
00356       break; \
00357    case AST_CAUSE_NORMAL_CLEARING: \
00358       break; \
00359    default: \
00360       numnochan++; \
00361       break; \
00362    } \
00363 } while (0)
00364 
00365 
00366 static int onedigit_goto(struct ast_channel *chan, const char *context, char exten, int pri) 
00367 {
00368    char rexten[2] = { exten, '\0' };
00369 
00370    if (context) {
00371       if (!ast_goto_if_exists(chan, context, rexten, pri))
00372          return 1;
00373    } else {
00374       if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
00375          return 1;
00376       else if (!ast_strlen_zero(chan->macrocontext)) {
00377          if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
00378             return 1;
00379       }
00380    }
00381    return 0;
00382 }
00383 
00384 
00385 static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
00386 {
00387    const char *context = S_OR(chan->macrocontext, chan->context);
00388    const char *exten = S_OR(chan->macroexten, chan->exten);
00389 
00390    return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : "";
00391 }
00392 
00393 static void senddialevent(struct ast_channel *src, struct ast_channel *dst)
00394 {
00395    /* XXX do we need also CallerIDnum ? */
00396    manager_event(EVENT_FLAG_CALL, "Dial", 
00397             "Source: %s\r\n"
00398             "Destination: %s\r\n"
00399             "CallerID: %s\r\n"
00400             "CallerIDName: %s\r\n"
00401             "SrcUniqueID: %s\r\n"
00402             "DestUniqueID: %s\r\n",
00403             src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"),
00404             S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid,
00405             dst->uniqueid);
00406 }
00407 
00408 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_localuser *outgoing, int *to, struct ast_flags *peerflags, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart, int priority_jump, int *result)
00409 {
00410    int numbusy = busystart;
00411    int numcongestion = congestionstart;
00412    int numnochan = nochanstart;
00413    int prestart = busystart + congestionstart + nochanstart;
00414    int orig = *to;
00415    struct ast_channel *peer = NULL;
00416    /* single is set if only one destination is enabled */
00417    int single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_NOINBAND));
00418    
00419    if (single) {
00420       /* Turn off hold music, etc */
00421       ast_deactivate_generator(in);
00422       /* If we are calling a single channel, make them compatible for in-band tone purpose */
00423       ast_channel_make_compatible(outgoing->chan, in);
00424    }
00425    
00426    
00427    while (*to && !peer) {
00428       struct dial_localuser *o;
00429       int pos = 0;   /* how many channels do we handle */
00430       int numlines = prestart;
00431       struct ast_channel *winner;
00432       struct ast_channel *watchers[AST_MAX_WATCHERS];
00433 
00434       watchers[pos++] = in;
00435       for (o = outgoing; o; o = o->next) {
00436          /* Keep track of important channels */
00437          if (ast_test_flag(o, DIAL_STILLGOING) && o->chan)
00438             watchers[pos++] = o->chan;
00439          numlines++;
00440       }
00441       if (pos == 1) {   /* only the input channel is available */
00442          if (numlines == (numbusy + numcongestion + numnochan)) {
00443             if (option_verbose > 2)
00444                ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
00445             if (numbusy)
00446                strcpy(status, "BUSY"); 
00447             else if (numcongestion)
00448                strcpy(status, "CONGESTION");
00449             else if (numnochan)
00450                strcpy(status, "CHANUNAVAIL");
00451             if (ast_opt_priority_jumping || priority_jump)
00452                ast_goto_if_exists(in, in->context, in->exten, in->priority + 101);
00453          } else {
00454             if (option_verbose > 2)
00455                ast_verbose(VERBOSE_PREFIX_3 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
00456          }
00457          *to = 0;
00458          return NULL;
00459       }
00460       winner = ast_waitfor_n(watchers, pos, to);
00461       for (o = outgoing; o; o = o->next) {
00462          struct ast_frame *f;
00463          struct ast_channel *c = o->chan;
00464 
00465          if (c == NULL)
00466             continue;
00467          if (ast_test_flag(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
00468             if (!peer) {
00469                if (option_verbose > 2)
00470                   ast_verbose(VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
00471                peer = c;
00472                ast_copy_flags(peerflags, o,
00473                          OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
00474                          OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
00475                          OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
00476                          OPT_CALLEE_PARK | OPT_CALLER_PARK |
00477                          DIAL_NOFORWARDHTML);
00478                ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
00479                ast_copy_string(c->exten, "", sizeof(c->exten));
00480             }
00481             continue;
00482          }
00483          if (c != winner)
00484             continue;
00485          if (!ast_strlen_zero(c->call_forward)) {
00486             char tmpchan[256];
00487             char *stuff;
00488             char *tech;
00489             int cause;
00490 
00491             ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
00492             if ((stuff = strchr(tmpchan, '/'))) {
00493                *stuff++ = '\0';
00494                tech = tmpchan;
00495             } else {
00496                const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
00497                snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
00498                stuff = tmpchan;
00499                tech = "Local";
00500             }
00501             /* Before processing channel, go ahead and check for forwarding */
00502             if (option_verbose > 2)
00503                ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
00504             /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
00505             if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) {
00506                if (option_verbose > 2)
00507                   ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
00508                c = o->chan = NULL;
00509                cause = AST_CAUSE_BUSY;
00510             } else {
00511                /* Setup parameters */
00512                if ((c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause))) {
00513                   if (single)
00514                      ast_channel_make_compatible(o->chan, in);
00515                   ast_channel_inherit_variables(in, o->chan);
00516                   ast_channel_datastore_inherit(in, o->chan);
00517                } else
00518                   ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
00519             }
00520             if (!c) {
00521                ast_clear_flag(o, DIAL_STILLGOING); 
00522                HANDLE_CAUSE(cause, in);
00523             } else {
00524                ast_rtp_make_compatible(c, in, single);
00525                if (c->cid.cid_num)
00526                   free(c->cid.cid_num);
00527                c->cid.cid_num = NULL;
00528                if (c->cid.cid_name)
00529                   free(c->cid.cid_name);
00530                c->cid.cid_name = NULL;
00531 
00532                if (ast_test_flag(o, OPT_FORCECLID)) {
00533                   c->cid.cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
00534                   ast_string_field_set(c, accountcode, winner->accountcode);
00535                   c->cdrflags = winner->cdrflags;
00536                } else {
00537                   c->cid.cid_num = ast_strdup(in->cid.cid_num);
00538                   c->cid.cid_name = ast_strdup(in->cid.cid_name);
00539                   ast_string_field_set(c, accountcode, in->accountcode);
00540                   c->cdrflags = in->cdrflags;
00541                }
00542 
00543                if (in->cid.cid_ani) {
00544                   if (c->cid.cid_ani)
00545                      free(c->cid.cid_ani);
00546                   c->cid.cid_ani = ast_strdup(in->cid.cid_ani);
00547                }
00548                if (c->cid.cid_rdnis) 
00549                   free(c->cid.cid_rdnis);
00550                c->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
00551                if (ast_call(c, tmpchan, 0)) {
00552                   ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
00553                   ast_clear_flag(o, DIAL_STILLGOING); 
00554                   ast_hangup(c);
00555                   c = o->chan = NULL;
00556                   numnochan++;
00557                } else {
00558                   senddialevent(in, c);
00559                   /* After calling, set callerid to extension */
00560                   if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) {
00561                      char cidname[AST_MAX_EXTENSION] = "";
00562                      ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
00563                   }
00564                }
00565             }
00566             /* Hangup the original channel now, in case we needed it */
00567             ast_hangup(winner);
00568             continue;
00569          }
00570          f = ast_read(winner);
00571          if (!f) {
00572             in->hangupcause = c->hangupcause;
00573             ast_hangup(c);
00574             c = o->chan = NULL;
00575             ast_clear_flag(o, DIAL_STILLGOING);
00576             HANDLE_CAUSE(in->hangupcause, in);
00577             continue;
00578          }
00579          if (f->frametype == AST_FRAME_CONTROL) {
00580             switch(f->subclass) {
00581             case AST_CONTROL_ANSWER:
00582                /* This is our guy if someone answered. */
00583                if (!peer) {
00584                   if (option_verbose > 2)
00585                      ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
00586                   peer = c;
00587                   ast_copy_flags(peerflags, o,
00588                             OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
00589                             OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
00590                             OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
00591                             OPT_CALLEE_PARK | OPT_CALLER_PARK |
00592                             DIAL_NOFORWARDHTML);
00593                   ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
00594                   ast_copy_string(c->exten, "", sizeof(c->exten));
00595                   /* Setup RTP early bridge if appropriate */
00596                   if (CAN_EARLY_BRIDGE(peerflags))
00597                      ast_rtp_early_bridge(in, peer);
00598                }
00599                /* If call has been answered, then the eventual hangup is likely to be normal hangup */
00600                in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
00601                c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
00602                break;
00603             case AST_CONTROL_BUSY:
00604                if (option_verbose > 2)
00605                   ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", c->name);
00606                in->hangupcause = c->hangupcause;
00607                ast_hangup(c);
00608                c = o->chan = NULL;
00609                ast_clear_flag(o, DIAL_STILLGOING); 
00610                HANDLE_CAUSE(AST_CAUSE_BUSY, in);
00611                break;
00612             case AST_CONTROL_CONGESTION:
00613                if (option_verbose > 2)
00614                   ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", c->name);
00615                in->hangupcause = c->hangupcause;
00616                ast_hangup(c);
00617                c = o->chan = NULL;
00618                ast_clear_flag(o, DIAL_STILLGOING);
00619                HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
00620                break;
00621             case AST_CONTROL_RINGING:
00622                                          if (ast_test_flag(peerflags, OPT_CALLBACK_INIT)) {
00623                                              if (option_verbose > 2)
00624                                                  ast_verbose( VERBOSE_PREFIX_3 "%s is ringing, hanging up.\n", o->chan->name);
00625                                              return NULL;
00626                                          } else {
00627                    if (option_verbose > 2)
00628                   ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name);
00629                    /* Setup early media if appropriate */
00630                    if (single && CAN_EARLY_BRIDGE(peerflags))
00631                   ast_rtp_early_bridge(in, c);
00632                    if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
00633                   ast_indicate(in, AST_CONTROL_RINGING);
00634                   (*sentringing)++;
00635                    }
00636                }
00637                break;
00638             case AST_CONTROL_PROGRESS:
00639                if (option_verbose > 2)
00640                   ast_verbose (VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", c->name, in->name);
00641                /* Setup early media if appropriate */
00642                if (single && CAN_EARLY_BRIDGE(peerflags))
00643                   ast_rtp_early_bridge(in, c);
00644                if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_NOINBAND))
00645                   ast_indicate(in, AST_CONTROL_PROGRESS);
00646                break;
00647             case AST_CONTROL_VIDUPDATE:
00648                if (option_verbose > 2)
00649                   ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", c->name, in->name);
00650                ast_indicate(in, AST_CONTROL_VIDUPDATE);
00651                break;
00652             case AST_CONTROL_PROCEEDING:
00653                if (option_verbose > 2)
00654                   ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name);
00655                if (single && CAN_EARLY_BRIDGE(peerflags))
00656                   ast_rtp_early_bridge(in, c);
00657                if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_NOINBAND))
00658                   ast_indicate(in, AST_CONTROL_PROCEEDING);
00659                break;
00660             case AST_CONTROL_HOLD:
00661                if (option_verbose > 2)
00662                   ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", c->name);
00663                ast_indicate(in, AST_CONTROL_HOLD);
00664                break;
00665             case AST_CONTROL_UNHOLD:
00666                if (option_verbose > 2)
00667                   ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", c->name);
00668                ast_indicate(in, AST_CONTROL_UNHOLD);
00669                break;
00670             case AST_CONTROL_OFFHOOK:
00671             case AST_CONTROL_FLASH:
00672                /* Ignore going off hook and flash */
00673                break;
00674             case -1:
00675                if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK | OPT_NOINBAND)) {
00676                   if (option_verbose > 2)
00677                      ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name);
00678                   ast_indicate(in, -1);
00679                   (*sentringing) = 0;
00680                }
00681                break;
00682             default:
00683                if (option_debug)
00684                   ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
00685             }
00686          } else if (single) {
00687             /* XXX are we sure the logic is correct ? or we should just switch on f->frametype ? */
00688             if (f->frametype == AST_FRAME_VOICE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
00689                if (ast_write(in, f)) 
00690                   ast_log(LOG_WARNING, "Unable to forward voice frame\n");
00691             } else if (f->frametype == AST_FRAME_IMAGE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
00692                if (ast_write(in, f))
00693                   ast_log(LOG_WARNING, "Unable to forward image\n");
00694             } else if (f->frametype == AST_FRAME_TEXT && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
00695                if (ast_write(in, f))
00696                   ast_log(LOG_WARNING, "Unable to send text\n");
00697             } else if (f->frametype == AST_FRAME_HTML && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) {
00698                if (ast_channel_sendhtml(in, f->subclass, f->data, f->datalen) == -1)
00699                   ast_log(LOG_WARNING, "Unable to send URL\n");
00700             }
00701          }
00702          ast_frfree(f);
00703       } /* end for */
00704       if (winner == in) {
00705          struct ast_frame *f = ast_read(in);
00706 #if 0
00707          if (f && (f->frametype != AST_FRAME_VOICE))
00708             printf("Frame type: %d, %d\n", f->frametype, f->subclass);
00709          else if (!f || (f->frametype != AST_FRAME_VOICE))
00710             printf("Hangup received on %s\n", in->name);
00711 #endif
00712          if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
00713             /* Got hung up */
00714             *to = -1;
00715             ast_cdr_noanswer(in->cdr);
00716             strcpy(status, "CANCEL");
00717             if (f)
00718                ast_frfree(f);
00719             return NULL;
00720          }
00721 
00722          if (f && (f->frametype == AST_FRAME_DTMF)) {
00723             if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) {
00724                const char *context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
00725                if (onedigit_goto(in, context, (char) f->subclass, 1)) {
00726                   if (option_verbose > 2)
00727                      ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
00728                   *to=0;
00729                   ast_cdr_noanswer(in->cdr);
00730                   *result = f->subclass;
00731                   strcpy(status, "CANCEL");
00732                   ast_frfree(f);
00733                   return NULL;
00734                }
00735             }
00736 
00737             if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) && 
00738                     (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
00739                if (option_verbose > 2)
00740                   ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
00741                *to=0;
00742                ast_cdr_noanswer(in->cdr);
00743                strcpy(status, "CANCEL");
00744                ast_frfree(f);
00745                return NULL;
00746             }
00747          }
00748 
00749          /* Forward HTML stuff */
00750          if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 
00751             if(ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen) == -1)
00752                ast_log(LOG_WARNING, "Unable to send URL\n");
00753          
00754 
00755          if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END)))  {
00756             if (ast_write(outgoing->chan, f))
00757                ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
00758          }
00759          if (single && (f->frametype == AST_FRAME_CONTROL) && 
00760             ((f->subclass == AST_CONTROL_HOLD) || 
00761              (f->subclass == AST_CONTROL_UNHOLD) || 
00762              (f->subclass == AST_CONTROL_VIDUPDATE))) {
00763             if (option_verbose > 2)
00764                ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
00765             ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen);
00766          }
00767          ast_frfree(f);
00768       }
00769       if (!*to && (option_verbose > 2))
00770          ast_verbose(VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
00771       if (!*to || ast_check_hangup(in)) {
00772          ast_cdr_noanswer(in->cdr);
00773       }
00774       
00775    }
00776    if (peer && !ast_cdr_log_unanswered()) {
00777       /* suppress the CDR's that didn't win */
00778       struct dial_localuser *o;
00779       for (o = outgoing; o; o = o->next) {
00780          struct ast_channel *c = o->chan;
00781          if (c && c != peer && c->cdr) {
00782             ast_set_flag(c->cdr, AST_CDR_FLAG_POST_DISABLED);
00783          }
00784       }
00785    } else if (!peer && !ast_cdr_log_unanswered()) {
00786          /* suppress the CDR's that didn't win */
00787       struct dial_localuser *o;
00788       for (o = outgoing; o; o = o->next) {
00789          struct ast_channel *c = o->chan;
00790          if (c && c->cdr) {
00791             ast_set_flag(c->cdr, AST_CDR_FLAG_POST_DISABLED);     
00792          }
00793       }
00794    }
00795    
00796    return peer;
00797 }
00798 
00799 static void replace_macro_delimiter(char *s)
00800 {
00801    for (; *s; s++)
00802       if (*s == '^')
00803          *s = '|';
00804 }
00805 
00806 
00807 /* returns true if there is a valid privacy reply */
00808 static int valid_priv_reply(struct ast_flags *opts, int res)
00809 {
00810    if (res < '1')
00811       return 0;
00812    if (ast_test_flag(opts, OPT_PRIVACY) && res <= '5')
00813       return 1;
00814    if (ast_test_flag(opts, OPT_SCREENING) && res <= '4')
00815       return 1;
00816    return 0;
00817 }
00818 
00819 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags, int *continue_exec)
00820 {
00821    int res = -1;
00822    struct ast_module_user *u;
00823    char *rest, *cur;
00824    struct dial_localuser *outgoing = NULL;
00825    struct ast_channel *peer;
00826    int to;
00827    int numbusy = 0;
00828    int numcongestion = 0;
00829    int numnochan = 0;
00830    int cause;
00831    char numsubst[256];
00832    char cidname[AST_MAX_EXTENSION] = "";
00833    int privdb_val = 0;
00834    unsigned int calldurationlimit = 0;
00835    long timelimit = 0;
00836    long play_warning = 0;
00837    long warning_freq = 0;
00838    const char *warning_sound = NULL;
00839    const char *end_sound = NULL;
00840    const char *start_sound = NULL;
00841    char *dtmfcalled = NULL, *dtmfcalling = NULL;
00842    char status[256] = "INVALIDARGS";
00843    int play_to_caller = 0, play_to_callee = 0;
00844    int sentringing = 0, moh = 0;
00845    const char *outbound_group = NULL;
00846    int result = 0;
00847    time_t start_time;
00848    char privintro[1024];
00849    char privcid[256];
00850    char *parse;
00851    int opermode = 0;
00852    AST_DECLARE_APP_ARGS(args,
00853               AST_APP_ARG(peers);
00854               AST_APP_ARG(timeout);
00855               AST_APP_ARG(options);
00856               AST_APP_ARG(url);
00857    );
00858    struct ast_flags opts = { 0, };
00859    char *opt_args[OPT_ARG_ARRAY_SIZE];
00860    struct ast_datastore *datastore = NULL;
00861    int fulldial = 0, num_dialed = 0;
00862 
00863    if (ast_strlen_zero(data)) {
00864       ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
00865       pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
00866       return -1;
00867    }
00868 
00869    u = ast_module_user_add(chan);
00870 
00871    parse = ast_strdupa(data);
00872    
00873    AST_STANDARD_APP_ARGS(args, parse);
00874 
00875    if (!ast_strlen_zero(args.options) &&
00876          ast_app_parse_options(dial_exec_options, &opts, opt_args, args.options)) {
00877       pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
00878       goto done;
00879    }
00880 
00881    if (ast_strlen_zero(args.peers)) {
00882       ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
00883       pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
00884       goto done;
00885    }
00886 
00887    if (ast_test_flag(&opts, OPT_OPERMODE)) {
00888       if (ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]))
00889          opermode = 1;
00890       else opermode = atoi(opt_args[OPT_ARG_OPERMODE]);
00891       if (option_verbose > 2)
00892          ast_verbose(VERBOSE_PREFIX_3 "Setting operator services mode to %d.\n", opermode);
00893    }
00894    
00895    if (ast_test_flag(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
00896       calldurationlimit = atoi(opt_args[OPT_ARG_DURATION_STOP]);
00897       if (!calldurationlimit) {
00898          ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
00899          pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
00900          goto done;
00901       }
00902       if (option_verbose > 2)
00903          ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
00904    }
00905 
00906    if (ast_test_flag(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
00907       dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
00908       dtmfcalled = strsep(&dtmfcalling, ":");
00909    }
00910 
00911    if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
00912       char *limit_str, *warning_str, *warnfreq_str;
00913       const char *var;
00914 
00915       warnfreq_str = opt_args[OPT_ARG_DURATION_LIMIT];
00916       limit_str = strsep(&warnfreq_str, ":");
00917       warning_str = strsep(&warnfreq_str, ":");
00918 
00919       timelimit = atol(limit_str);
00920       if (warning_str)
00921          play_warning = atol(warning_str);
00922       if (warnfreq_str)
00923          warning_freq = atol(warnfreq_str);
00924 
00925       if (!timelimit) {
00926          ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
00927          goto done;
00928       } else if (play_warning > timelimit) {
00929          /* If the first warning is requested _after_ the entire call would end,
00930             and no warning frequency is requested, then turn off the warning. If
00931             a warning frequency is requested, reduce the 'first warning' time by
00932             that frequency until it falls within the call's total time limit.
00933          */
00934 
00935          if (!warning_freq) {
00936             play_warning = 0;
00937          } else {
00938             /* XXX fix this!! */
00939             while (play_warning > timelimit)
00940                play_warning -= warning_freq;
00941             if (play_warning < 1)
00942                play_warning = warning_freq = 0;
00943          }
00944       }
00945 
00946       var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
00947       play_to_caller = var ? ast_true(var) : 1;
00948       
00949       var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
00950       play_to_callee = var ? ast_true(var) : 0;
00951       
00952       if (!play_to_caller && !play_to_callee)
00953          play_to_caller = 1;
00954       
00955       var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
00956       warning_sound = S_OR(var, "timeleft");
00957       
00958       var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
00959       end_sound = S_OR(var, NULL);  /* XXX not much of a point in doing this! */
00960       
00961       var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
00962       start_sound = S_OR(var, NULL);   /* XXX not much of a point in doing this! */
00963 
00964       /* undo effect of S(x) in case they are both used */
00965       calldurationlimit = 0;
00966       /* more efficient to do it like S(x) does since no advanced opts */
00967       if (!play_warning && !start_sound && !end_sound && timelimit) {
00968          calldurationlimit = timelimit / 1000;
00969          if (option_verbose > 2)
00970             ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
00971          timelimit = play_to_caller = play_to_callee = play_warning = warning_freq = 0;
00972       } else if (option_verbose > 2) {
00973          ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n");
00974          ast_verbose(VERBOSE_PREFIX_4 "timelimit      = %ld\n", timelimit);
00975          ast_verbose(VERBOSE_PREFIX_4 "play_warning   = %ld\n", play_warning);
00976          ast_verbose(VERBOSE_PREFIX_4 "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
00977          ast_verbose(VERBOSE_PREFIX_4 "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
00978          ast_verbose(VERBOSE_PREFIX_4 "warning_freq   = %ld\n", warning_freq);
00979          ast_verbose(VERBOSE_PREFIX_4 "start_sound    = %s\n", start_sound);
00980          ast_verbose(VERBOSE_PREFIX_4 "warning_sound  = %s\n", warning_sound);
00981          ast_verbose(VERBOSE_PREFIX_4 "end_sound      = %s\n", end_sound);
00982       }
00983    }
00984 
00985    if (ast_test_flag(&opts, OPT_RESETCDR) && chan->cdr)
00986       ast_cdr_reset(chan->cdr, NULL);
00987    if (ast_test_flag(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
00988       opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
00989    if (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) {
00990       char callerid[60];
00991       char *l = chan->cid.cid_num;  /* XXX watch out, we are overwriting it */
00992       if (!ast_strlen_zero(l)) {
00993          ast_shrink_phone_number(l);
00994          if( ast_test_flag(&opts, OPT_PRIVACY) ) {
00995             if (option_verbose > 2)
00996                ast_verbose(VERBOSE_PREFIX_3  "Privacy DB is '%s', clid is '%s'\n",
00997                        opt_args[OPT_ARG_PRIVACY], l);
00998             privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
00999          }
01000          else {
01001             if (option_verbose > 2)
01002                ast_verbose(VERBOSE_PREFIX_3  "Privacy Screening, clid is '%s'\n", l);
01003             privdb_val = AST_PRIVACY_UNKNOWN;
01004          }
01005       } else {
01006          char *tnam, *tn2;
01007 
01008          tnam = ast_strdupa(chan->name);
01009          /* clean the channel name so slashes don't try to end up in disk file name */
01010          for(tn2 = tnam; *tn2; tn2++) {
01011             if( *tn2=='/')
01012                *tn2 = '=';  /* any other chars to be afraid of? */
01013          }
01014          if (option_verbose > 2)
01015             ast_verbose(VERBOSE_PREFIX_3  "Privacy-- callerid is empty\n");
01016 
01017          snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
01018          l = callerid;
01019          privdb_val = AST_PRIVACY_UNKNOWN;
01020       }
01021       
01022       ast_copy_string(privcid,l,sizeof(privcid));
01023 
01024       if( strncmp(privcid,"NOCALLERID",10) != 0 && ast_test_flag(&opts, OPT_SCREEN_NOCLID) ) { /* if callerid is set, and ast_test_flag(&opts, OPT_SCREEN_NOCLID) is set also */  
01025          if (option_verbose > 2)
01026             ast_verbose( VERBOSE_PREFIX_3  "CallerID set (%s); N option set; Screening should be off\n", privcid);
01027          privdb_val = AST_PRIVACY_ALLOW;
01028       }
01029       else if(ast_test_flag(&opts, OPT_SCREEN_NOCLID) && strncmp(privcid,"NOCALLERID",10) == 0 ) {
01030          if (option_verbose > 2)
01031             ast_verbose( VERBOSE_PREFIX_3  "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val);
01032       }
01033       
01034       if(privdb_val == AST_PRIVACY_DENY ) {
01035          ast_copy_string(status, "NOANSWER", sizeof(status));
01036          if (option_verbose > 2)
01037             ast_verbose( VERBOSE_PREFIX_3  "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
01038          res=0;
01039          goto out;
01040       }
01041       else if(privdb_val == AST_PRIVACY_KILL ) {
01042          ast_copy_string(status, "DONTCALL", sizeof(status));
01043          if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
01044             ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
01045          }
01046          res = 0;
01047          goto out; /* Is this right? */
01048       }
01049       else if(privdb_val == AST_PRIVACY_TORTURE ) {
01050          ast_copy_string(status, "TORTURE", sizeof(status));
01051          if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
01052             ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
01053          }
01054          res = 0;
01055          goto out; /* is this right??? */
01056       }
01057       else if(privdb_val == AST_PRIVACY_UNKNOWN ) {
01058          /* Get the user's intro, store it in priv-callerintros/$CID, 
01059             unless it is already there-- this should be done before the 
01060             call is actually dialed  */
01061 
01062          /* make sure the priv-callerintros dir actually exists */
01063          snprintf(privintro, sizeof(privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
01064          if (mkdir(privintro, 0755) && errno != EEXIST) {
01065             ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(errno));
01066             res = -1;
01067             goto out;
01068          }
01069 
01070          snprintf(privintro,sizeof(privintro), "priv-callerintros/%s", privcid);
01071          if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) {
01072             /* the DELUX version of this code would allow this caller the
01073                option to hear and retape their previously recorded intro.
01074             */
01075          }
01076          else {
01077             int duration; /* for feedback from play_and_wait */
01078             /* the file doesn't exist yet. Let the caller submit his
01079                vocal intro for posterity */
01080             /* priv-recordintro script:
01081 
01082                "At the tone, please say your name:"
01083 
01084             */
01085             ast_answer(chan);
01086             res = ast_play_and_record(chan, "priv-recordintro", privintro, 4, "gsm", &duration, 128, 2000, 0);  /* NOTE: I've reduced the total time to 4 sec */
01087                               /* don't think we'll need a lock removed, we took care of
01088                                  conflicts by naming the privintro file */
01089             if (res == -1) {
01090                /* Delete the file regardless since they hung up during recording */
01091                                         ast_filedelete(privintro, NULL);
01092                                         if( ast_fileexists(privintro,NULL,NULL ) > 0 )
01093                                                 ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro);
01094                                         else if (option_verbose > 2)
01095                                                 ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
01096                goto out;
01097             }
01098                                 if( !ast_streamfile(chan, "vm-dialout", chan->language) )
01099                                         ast_waitstream(chan, "");
01100          }
01101       }
01102    }
01103 
01104    if (continue_exec)
01105       *continue_exec = 0;
01106    
01107    /* If a channel group has been specified, get it for use when we create peer channels */
01108    if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) {
01109       outbound_group = ast_strdupa(outbound_group);
01110       pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL);
01111    } else {
01112       outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
01113    }
01114        
01115    ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_CALLBACK_INIT | OPT_NOINBAND);
01116    /* loop through the list of dial destinations */
01117    rest = args.peers;
01118    while ((cur = strsep(&rest, "&")) ) {
01119       struct dial_localuser *tmp;
01120       /* Get a technology/[device:]number pair */
01121       char *number = cur;
01122       char *interface = ast_strdupa(number);
01123       char *tech = strsep(&number, "/");
01124       /* find if we already dialed this interface */
01125       struct ast_dialed_interface *di;
01126       AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
01127       num_dialed++;
01128       if (!number) {
01129          ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
01130          goto out;
01131       }
01132       if (!(tmp = ast_calloc(1, sizeof(*tmp))))
01133          goto out;
01134       if (opts.flags) {
01135          ast_copy_flags(tmp, &opts,
01136                    OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
01137                    OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
01138                    OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
01139                    OPT_CALLEE_PARK | OPT_CALLER_PARK |
01140                    OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID | OPT_NOINBAND);
01141          ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);  
01142       }
01143       ast_copy_string(numsubst, number, sizeof(numsubst));
01144       /* Request the peer */
01145 
01146       ast_channel_lock(chan);
01147       datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL);
01148       ast_channel_unlock(chan);
01149 
01150       if (datastore)
01151          dialed_interfaces = datastore->data;
01152       else {
01153          if (!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) {
01154             ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n"); 
01155             free(tmp);
01156             goto out;
01157          }
01158 
01159          datastore->inheritance = DATASTORE_INHERIT_FOREVER;
01160 
01161          if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
01162             free(tmp);
01163             goto out;
01164          }
01165 
01166          datastore->data = dialed_interfaces;
01167          AST_LIST_HEAD_INIT(dialed_interfaces);
01168 
01169          ast_channel_lock(chan);
01170          ast_channel_datastore_add(chan, datastore);
01171          ast_channel_unlock(chan);
01172       }
01173 
01174       AST_LIST_LOCK(dialed_interfaces);
01175       AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
01176          if (!strcasecmp(di->interface, interface)) {
01177             ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n", 
01178                di->interface);
01179             break;
01180          }
01181       }
01182       AST_LIST_UNLOCK(dialed_interfaces);
01183 
01184       if (di) {
01185          fulldial++;
01186          free(tmp);
01187          continue;
01188       }
01189 
01190       /* It is always ok to dial a Local interface.  We only keep track of
01191        * which "real" interfaces have been dialed.  The Local channel will
01192        * inherit this list so that if it ends up dialing a real interface,
01193        * it won't call one that has already been called. */
01194       if (strcasecmp(tech, "Local")) {
01195          if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) {
01196             AST_LIST_UNLOCK(dialed_interfaces);
01197             free(tmp);
01198             goto out;
01199          }
01200          strcpy(di->interface, interface);
01201 
01202          AST_LIST_LOCK(dialed_interfaces);
01203          AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
01204          AST_LIST_UNLOCK(dialed_interfaces);
01205       }
01206 
01207       tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
01208       if (!tmp->chan) {
01209          /* If we can't, just go on to the next call */
01210          ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
01211          HANDLE_CAUSE(cause, chan);
01212          if (!rest)  /* we are on the last destination */
01213             chan->hangupcause = cause;
01214          free(tmp);
01215          continue;
01216       }
01217 
01218             pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
01219 
01220       /* Setup outgoing SDP to match incoming one */
01221       ast_rtp_make_compatible(tmp->chan, chan, !outgoing && !rest);
01222       
01223       /* Inherit specially named variables from parent channel */
01224       ast_channel_inherit_variables(chan, tmp->chan);
01225 
01226       tmp->chan->appl = "AppDial";
01227       tmp->chan->data = "(Outgoing Line)";
01228       tmp->chan->whentohangup = 0;
01229 
01230       if (tmp->chan->cid.cid_num)
01231          free(tmp->chan->cid.cid_num);
01232       tmp->chan->cid.cid_num = ast_strdup(chan->cid.cid_num);
01233 
01234       if (tmp->chan->cid.cid_name)
01235          free(tmp->chan->cid.cid_name);
01236       tmp->chan->cid.cid_name = ast_strdup(chan->cid.cid_name);
01237 
01238       if (tmp->chan->cid.cid_ani)
01239          free(tmp->chan->cid.cid_ani);
01240       tmp->chan->cid.cid_ani = ast_strdup(chan->cid.cid_ani);
01241       
01242       /* Copy language from incoming to outgoing */
01243       ast_string_field_set(tmp->chan, language, chan->language);
01244       ast_string_field_set(tmp->chan, accountcode, chan->accountcode);
01245       tmp->chan->cdrflags = chan->cdrflags;
01246       if (ast_strlen_zero(tmp->chan->musicclass))
01247          ast_string_field_set(tmp->chan, musicclass, chan->musicclass);
01248       /* XXX don't we free previous values ? */
01249       tmp->chan->cid.cid_rdnis = ast_strdup(chan->cid.cid_rdnis);
01250       /* Pass callingpres setting */
01251       tmp->chan->cid.cid_pres = chan->cid.cid_pres;
01252       /* Pass type of number */
01253       tmp->chan->cid.cid_ton = chan->cid.cid_ton;
01254       /* Pass type of tns */
01255       tmp->chan->cid.cid_tns = chan->cid.cid_tns;
01256       /* Presense of ADSI CPE on outgoing channel follows ours */
01257       tmp->chan->adsicpe = chan->adsicpe;
01258       /* Pass the transfer capability */
01259       tmp->chan->transfercapability = chan->transfercapability;
01260 
01261       /* If we have an outbound group, set this peer channel to it */
01262       if (outbound_group)
01263          ast_app_group_set_channel(tmp->chan, outbound_group);
01264 
01265       /* Inherit context and extension */
01266       if (!ast_strlen_zero(chan->macrocontext))
01267          ast_copy_string(tmp->chan->dialcontext, chan->macrocontext, sizeof(tmp->chan->dialcontext));
01268       else
01269          ast_copy_string(tmp->chan->dialcontext, chan->context, sizeof(tmp->chan->dialcontext));
01270       if (!ast_strlen_zero(chan->macroexten))
01271          ast_copy_string(tmp->chan->exten, chan->macroexten, sizeof(tmp->chan->exten));
01272       else
01273          ast_copy_string(tmp->chan->exten, chan->exten, sizeof(tmp->chan->exten));
01274 
01275       /* Place the call, but don't wait on the answer */
01276       res = ast_call(tmp->chan, numsubst, 0);
01277 
01278       /* Save the info in cdr's that we called them */
01279       if (chan->cdr)
01280          ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
01281 
01282       /* check the results of ast_call */
01283       if (res) {
01284          /* Again, keep going even if there's an error */
01285          if (option_debug)
01286             ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
01287          if (option_verbose > 2)
01288             ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
01289          ast_hangup(tmp->chan);
01290          tmp->chan = NULL;
01291          free(tmp);
01292          continue;
01293       } else {
01294          senddialevent(chan, tmp->chan);
01295          if (option_verbose > 2)
01296             ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
01297          if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID))
01298             ast_set_callerid(tmp->chan, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
01299       }
01300       /* Put them in the list of outgoing thingies...  We're ready now. 
01301          XXX If we're forcibly removed, these outgoing calls won't get
01302          hung up XXX */
01303       ast_set_flag(tmp, DIAL_STILLGOING); 
01304       tmp->next = outgoing;
01305       outgoing = tmp;
01306       /* If this line is up, don't try anybody else */
01307       if (outgoing->chan->_state == AST_STATE_UP)
01308          break;
01309    }
01310    
01311    if (ast_strlen_zero(args.timeout)) {
01312       to = -1;
01313    } else {
01314       to = atoi(args.timeout);
01315       if (to > 0)
01316          to *= 1000;
01317       else
01318          ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
01319    }
01320 
01321    if (!outgoing) {
01322       ast_copy_string(status, "CHANUNAVAIL", sizeof(status));
01323       if(fulldial == num_dialed) {
01324          res = -1;
01325          goto out;
01326       }
01327       /* See if there is a special message */
01328       ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
01329    } else {
01330       /* Our status will at least be NOANSWER */
01331       ast_copy_string(status, "NOANSWER", sizeof(status));
01332       if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
01333          moh = 1;
01334          if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01335             char *original_moh = ast_strdupa(chan->musicclass);
01336             ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01337             ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01338             ast_string_field_set(chan, musicclass, original_moh);
01339          } else {
01340             ast_moh_start(chan, NULL, NULL);
01341          }
01342          ast_indicate(chan, AST_CONTROL_PROGRESS);
01343       } else if (ast_test_flag(outgoing, OPT_RINGBACK | OPT_NOINBAND)) {
01344          ast_indicate(chan, AST_CONTROL_RINGING);
01345          sentringing++;
01346       }
01347    }
01348 
01349    time(&start_time);
01350    peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
01351 
01352    ast_channel_datastore_remove(chan, datastore);
01353    ast_channel_datastore_free(datastore);
01354    if (!peer) {
01355       if (result) {
01356          res = result;
01357       } else if (to) { /* Musta gotten hung up */
01358          res = -1;
01359       } else { /* Nobody answered, next please? */
01360          res = 0;
01361       }
01362       /* almost done, although the 'else' block is 400 lines */
01363    } else {
01364       const char *number;
01365       time_t end_time, answer_time = time(NULL);
01366 
01367       strcpy(status, "ANSWER");
01368       /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
01369          we will always return with -1 so that it is hung up properly after the 
01370          conversation.  */
01371       hanguptree(outgoing, peer);
01372       outgoing = NULL;
01373       /* If appropriate, log that we have a destination channel */
01374       if (chan->cdr)
01375          ast_cdr_setdestchan(chan->cdr, peer->name);
01376       if (peer->name)
01377          pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
01378 
01379       number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
01380       if (!number)
01381          number = numsubst;
01382       pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
01383       if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
01384          if (option_debug)
01385             ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", args.url);
01386          ast_channel_sendurl( peer, args.url );
01387       }
01388       if ( (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) && privdb_val == AST_PRIVACY_UNKNOWN) {
01389          int res2;
01390          int loopcount = 0;
01391 
01392          /* Get the user's intro, store it in priv-callerintros/$CID, 
01393             unless it is already there-- this should be done before the 
01394             call is actually dialed  */
01395 
01396          /* all ring indications and moh for the caller has been halted as soon as the 
01397             target extension was picked up. We are going to have to kill some
01398             time and make the caller believe the peer hasn't picked up yet */
01399 
01400          if (ast_test_flag(&opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01401             char *original_moh = ast_strdupa(chan->musicclass);
01402             ast_indicate(chan, -1);
01403             ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01404             ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01405             ast_string_field_set(chan, musicclass, original_moh);
01406          } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
01407             ast_indicate(chan, AST_CONTROL_RINGING);
01408             sentringing++;
01409          }
01410 
01411          /* Start autoservice on the other chan ?? */
01412          res2 = ast_autoservice_start(chan);
01413          /* Now Stream the File */
01414          for (loopcount = 0; loopcount < 3; loopcount++) {
01415             if (res2 && loopcount == 0)   /* error in ast_autoservice_start() */
01416                break;
01417             if (!res2)  /* on timeout, play the message again */
01418                res2 = ast_play_and_wait(peer,"priv-callpending");
01419             if (!valid_priv_reply(&opts, res2))
01420                res2 = 0;
01421             /* priv-callpending script: 
01422                "I have a caller waiting, who introduces themselves as:"
01423             */
01424             if (!res2)
01425                res2 = ast_play_and_wait(peer,privintro);
01426             if (!valid_priv_reply(&opts, res2))
01427                res2 = 0;
01428             /* now get input from the called party, as to their choice */
01429             if( !res2 ) {
01430                /* XXX can we have both, or they are mutually exclusive ? */
01431                if( ast_test_flag(&opts, OPT_PRIVACY) )
01432                   res2 = ast_play_and_wait(peer,"priv-callee-options");
01433                if( ast_test_flag(&opts, OPT_SCREENING) )
01434                   res2 = ast_play_and_wait(peer,"screen-callee-options");
01435             }
01436             /*! \page DialPrivacy Dial Privacy scripts
01437             \par priv-callee-options script:
01438                "Dial 1 if you wish this caller to reach you directly in the future,
01439                   and immediately connect to their incoming call
01440                 Dial 2 if you wish to send this caller to voicemail now and 
01441                   forevermore.
01442                 Dial 3 to send this caller to the torture menus, now and forevermore.
01443                 Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
01444                 Dial 5 to allow this caller to come straight thru to you in the future,
01445                   but right now, just this once, send them to voicemail."
01446             \par screen-callee-options script:
01447                "Dial 1 if you wish to immediately connect to the incoming call
01448                 Dial 2 if you wish to send this caller to voicemail.
01449                 Dial 3 to send this caller to the torture menus.
01450                 Dial 4 to send this caller to a simple "go away" menu.
01451             */
01452             if (valid_priv_reply(&opts, res2))
01453                break;
01454             /* invalid option */
01455             res2 = ast_play_and_wait(peer, "vm-sorry");
01456          }
01457 
01458          if (ast_test_flag(&opts, OPT_MUSICBACK)) {
01459             ast_moh_stop(chan);
01460          } else if (ast_test_flag(&opts, OPT_RINGBACK | OPT_NOINBAND)) {
01461             ast_indicate(chan, -1);
01462             sentringing=0;
01463          }
01464          ast_autoservice_stop(chan);
01465 
01466          switch (res2) {
01467          case '1':
01468             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01469                if (option_verbose > 2)
01470                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
01471                           opt_args[OPT_ARG_PRIVACY], privcid);
01472                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
01473             }
01474             break;
01475          case '2':
01476             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01477                if (option_verbose > 2)
01478                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n",
01479                           opt_args[OPT_ARG_PRIVACY], privcid);
01480                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
01481             }
01482             ast_copy_string(status, "NOANSWER", sizeof(status));
01483             ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
01484             res=0;
01485             goto out;
01486          case '3':
01487             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01488                if (option_verbose > 2)
01489                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n",
01490                           opt_args[OPT_ARG_PRIVACY], privcid);
01491                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_TORTURE);
01492             }
01493             ast_copy_string(status, "TORTURE", sizeof(status));
01494             
01495             res = 0;
01496             ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
01497             goto out; /* Is this right? */
01498          case '4':
01499             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01500                if (option_verbose > 2)
01501                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n",
01502                           opt_args[OPT_ARG_PRIVACY], privcid);
01503                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_KILL);
01504             }
01505 
01506             ast_copy_string(status, "DONTCALL", sizeof(status));
01507             res = 0;
01508             ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
01509             goto out; /* Is this right? */
01510          case '5':
01511             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01512                if (option_verbose > 2)
01513                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
01514                           opt_args[OPT_ARG_PRIVACY], privcid);
01515                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
01516                ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
01517                res=0;
01518                goto out;
01519             } /* if not privacy, then 5 is the same as "default" case */
01520          default: /* bad input or -1 if failure to start autoservice */
01521             /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do?  */
01522             /* well, there seems basically two choices. Just patch the caller thru immediately,
01523                  or,... put 'em thru to voicemail. */
01524             /* since the callee may have hung up, let's do the voicemail thing, no database decision */
01525             ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
01526             ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
01527             res=0;
01528             goto out;
01529          }
01530 
01531          /* XXX once again, this path is only taken in the case '1', so it could be
01532           * moved there, although i am not really sure that this is correct - maybe
01533           * the check applies to other cases as well.
01534           */
01535          /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll 
01536             just clog things up, and it's not useful information, not being tied to a CID */
01537          if( strncmp(privcid,"NOCALLERID",10) == 0 || ast_test_flag(&opts, OPT_SCREEN_NOINTRO) ) {
01538             ast_filedelete(privintro, NULL);
01539             if( ast_fileexists(privintro, NULL, NULL ) > 0 )
01540                ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", privintro);
01541             else if (option_verbose > 2)
01542                ast_verbose(VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
01543          }
01544       }
01545       if (!ast_test_flag(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
01546          res = 0;
01547       } else {
01548          int digit = 0;
01549          /* Start autoservice on the other chan */
01550          res = ast_autoservice_start(chan);
01551          /* Now Stream the File */
01552          if (!res)
01553             res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
01554          if (!res) {
01555             digit = ast_waitstream(peer, AST_DIGIT_ANY); 
01556          }
01557          /* Ok, done. stop autoservice */
01558          res = ast_autoservice_stop(chan);
01559          if (digit > 0 && !res)
01560             res = ast_senddigit(chan, digit); 
01561          else
01562             res = digit;
01563 
01564       }
01565 
01566       if (chan && peer && ast_test_flag(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
01567          replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
01568          ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
01569          /* peer goes to the same context and extension as chan, so just copy info from chan*/
01570          ast_copy_string(peer->context, chan->context, sizeof(peer->context));
01571          ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
01572          peer->priority = chan->priority + 2;
01573          ast_pbx_start(peer);
01574          hanguptree(outgoing, NULL);
01575          if (continue_exec)
01576             *continue_exec = 1;
01577          res = 0;
01578          goto done;
01579       }
01580 
01581       if (ast_test_flag(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
01582          struct ast_app *theapp;
01583          const char *macro_result;
01584 
01585          res = ast_autoservice_start(chan);
01586          if (res) {
01587             ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
01588             res = -1;
01589          }
01590 
01591          theapp = pbx_findapp("Macro");
01592 
01593          if (theapp && !res) {   /* XXX why check res here ? */
01594             replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
01595             res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
01596             ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
01597             res = 0;
01598          } else {
01599             ast_log(LOG_ERROR, "Could not find application Macro\n");
01600             res = -1;
01601          }
01602 
01603          if (ast_autoservice_stop(chan) < 0) {
01604             ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
01605             res = -1;
01606          }
01607 
01608          if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
01609                char *macro_transfer_dest;
01610 
01611                if (!strcasecmp(macro_result, "BUSY")) {
01612                   ast_copy_string(status, macro_result, sizeof(status));
01613                   if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
01614                      if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
01615                         ast_set_flag(peerflags, OPT_GO_ON);
01616                      }
01617                   } else
01618                      ast_set_flag(peerflags, OPT_GO_ON);
01619                   res = -1;
01620                } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
01621                   ast_copy_string(status, macro_result, sizeof(status));
01622                   ast_set_flag(peerflags, OPT_GO_ON); 
01623                   res = -1;
01624                } else if (!strcasecmp(macro_result, "CONTINUE")) {
01625                   /* hangup peer and keep chan alive assuming the macro has changed 
01626                      the context / exten / priority or perhaps 
01627                      the next priority in the current exten is desired.
01628                   */
01629                   ast_set_flag(peerflags, OPT_GO_ON); 
01630                   res = -1;
01631                } else if (!strcasecmp(macro_result, "ABORT")) {
01632                   /* Hangup both ends unless the caller has the g flag */
01633                   res = -1;
01634                } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
01635                   res = -1;
01636                   /* perform a transfer to a new extension */
01637                   if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/
01638                      replace_macro_delimiter(macro_transfer_dest);
01639                      if (!ast_parseable_goto(chan, macro_transfer_dest))
01640                         ast_set_flag(peerflags, OPT_GO_ON);
01641 
01642                   }
01643                }
01644          }
01645       }
01646 
01647       if (!res) {
01648          if (calldurationlimit > 0) {
01649             peer->whentohangup = time(NULL) + calldurationlimit;
01650          }
01651          if (!ast_strlen_zero(dtmfcalled)) { 
01652             if (option_verbose > 2)
01653                ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n", dtmfcalled);
01654             res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
01655          }
01656          if (!ast_strlen_zero(dtmfcalling)) {
01657             if (option_verbose > 2)
01658                ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
01659             res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
01660          }
01661       }
01662       
01663       if (!res) {
01664          struct ast_bridge_config config;
01665 
01666          memset(&config,0,sizeof(struct ast_bridge_config));
01667          if (play_to_caller)
01668             ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
01669          if (play_to_callee)
01670             ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
01671          if ((chan->transfercapability != AST_TRANS_CAP_DIGITAL) && (chan->transfercapability != AST_TRANS_CAP_RESTRICTED_DIGITAL)) {
01672              /* only non-digital calls are allowed to go through userspace */
01673              if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
01674             ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
01675              if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
01676             ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
01677              if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
01678             ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
01679              if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
01680             ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
01681              if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
01682             ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
01683              if (ast_test_flag(peerflags, OPT_CALLER_MONITOR)) 
01684             ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
01685              if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
01686             ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
01687              if (ast_test_flag(peerflags, OPT_CALLER_PARK))
01688             ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
01689          }
01690          config.timelimit = timelimit;
01691          config.play_warning = play_warning;
01692          config.warning_freq = warning_freq;
01693          config.warning_sound = warning_sound;
01694          config.end_sound = end_sound;
01695          config.start_sound = start_sound;
01696          if (moh) {
01697             moh = 0;
01698             ast_moh_stop(chan);
01699          } else if (sentringing) {
01700             sentringing = 0;
01701             ast_indicate(chan, -1);
01702          }
01703          /* Be sure no generators are left on it */
01704          ast_deactivate_generator(chan);
01705          /* Make sure channels are compatible */
01706          res = ast_channel_make_compatible(chan, peer);
01707          if (res < 0) {
01708             ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
01709             ast_hangup(peer);
01710             res = -1;
01711             goto done;
01712          }
01713          if (opermode && (!strncmp(chan->name,"Zap",3)) &&
01714             (!strncmp(peer->name,"Zap",3)))
01715          {
01716             struct oprmode oprmode;
01717 
01718             oprmode.peer = peer;
01719             oprmode.mode = opermode;
01720 
01721             ast_channel_setoption(chan,
01722                AST_OPTION_OPRMODE,&oprmode,sizeof(struct oprmode),0);
01723          }
01724          res = ast_bridge_call(chan,peer,&config);
01725          time(&end_time);
01726          {
01727             char toast[80];
01728             snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
01729             pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
01730          }
01731       } else {
01732          time(&end_time);
01733          res = -1;
01734       }
01735       {
01736          char toast[80];
01737          snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
01738          pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
01739       }
01740       
01741       if (res != AST_PBX_NO_HANGUP_PEER) {
01742          if (!chan->_softhangup)
01743             chan->hangupcause = peer->hangupcause;
01744          ast_hangup(peer);
01745       }
01746    }  
01747 out:
01748    if (moh) {
01749       moh = 0;
01750       ast_moh_stop(chan);
01751    } else if (sentringing) {
01752       sentringing = 0;
01753       ast_indicate(chan, -1);
01754    }
01755    ast_rtp_early_bridge(chan, NULL);
01756    hanguptree(outgoing, NULL);
01757    pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
01758    if (option_debug)
01759       ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
01760    
01761    if ((ast_test_flag(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE)) {
01762       if (calldurationlimit)
01763          chan->whentohangup = 0;
01764       res = 0;
01765    }
01766 
01767 done:
01768    ast_module_user_remove(u);    
01769    return res;
01770 }
01771 
01772 static int dial_exec(struct ast_channel *chan, void *data)
01773 {
01774    struct ast_flags peerflags;
01775 
01776    memset(&peerflags, 0, sizeof(peerflags));
01777 
01778    return dial_exec_full(chan, data, &peerflags, NULL);
01779 }
01780 
01781 static int retrydial_exec(struct ast_channel *chan, void *data)
01782 {
01783    char *announce = NULL, *dialdata = NULL;
01784    const char *context = NULL;
01785    int sleep = 0, loops = 0, res = -1;
01786    struct ast_module_user *u;
01787    struct ast_flags peerflags;
01788    
01789    if (ast_strlen_zero(data)) {
01790       ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
01791       return -1;
01792    }  
01793 
01794    u = ast_module_user_add(chan);
01795 
01796    announce = ast_strdupa(data);
01797 
01798    memset(&peerflags, 0, sizeof(peerflags));
01799 
01800    if ((dialdata = strchr(announce, '|'))) {
01801       *dialdata++ = '\0';
01802       if (sscanf(dialdata, "%d", &sleep) == 1) {
01803          sleep *= 1000;
01804       } else {
01805          ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
01806          goto done;
01807       }
01808       if ((dialdata = strchr(dialdata, '|'))) {
01809          *dialdata++ = '\0';
01810          if (sscanf(dialdata, "%d", &loops) != 1) {
01811             ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
01812             goto done;
01813          }
01814       }
01815    }
01816    
01817    if ((dialdata = strchr(dialdata, '|'))) {
01818       *dialdata++ = '\0';
01819    } else {
01820       ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
01821       goto done;
01822    }
01823       
01824    if (sleep < 1000)
01825       sleep = 10000;
01826 
01827    if (!loops)
01828       loops = -1; /* run forever */
01829    
01830    context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
01831 
01832    res = 0;
01833    while (loops) {
01834       int continue_exec;
01835 
01836       chan->data = "Retrying";
01837       if (ast_test_flag(chan, AST_FLAG_MOH))
01838          ast_moh_stop(chan);
01839 
01840       res = dial_exec_full(chan, dialdata, &peerflags, &continue_exec);
01841       if (continue_exec)
01842          break;
01843 
01844       if (res == 0) {
01845          if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) {
01846             if (!ast_strlen_zero(announce)) {
01847                if (ast_fileexists(announce, NULL, chan->language) > 0) {
01848                   if(!(res = ast_streamfile(chan, announce, chan->language)))                      
01849                      ast_waitstream(chan, AST_DIGIT_ANY);
01850                } else
01851                   ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce);
01852             }
01853             if (!res && sleep) {
01854                if (!ast_test_flag(chan, AST_FLAG_MOH))
01855                   ast_moh_start(chan, NULL, NULL);
01856                res = ast_waitfordigit(chan, sleep);
01857             }
01858          } else {
01859             if (!ast_strlen_zero(announce)) {
01860                if (ast_fileexists(announce, NULL, chan->language) > 0) {
01861                   if (!(res = ast_streamfile(chan, announce, chan->language)))
01862                      res = ast_waitstream(chan, "");
01863                } else
01864                   ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce);
01865             }
01866             if (sleep) {
01867                if (!ast_test_flag(chan, AST_FLAG_MOH))
01868                   ast_moh_start(chan, NULL, NULL);
01869                if (!res)
01870                   res = ast_waitfordigit(chan, sleep);
01871             }
01872          }
01873       }
01874 
01875       if (res < 0)
01876          break;
01877       else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
01878          if (onedigit_goto(chan, context, (char) res, 1)) {
01879             res = 0;
01880             break;
01881          }
01882       }
01883       loops--;
01884    }
01885    if (loops == 0)
01886       res = 0;
01887    else if (res == 1)
01888       res = 0;
01889 
01890    if (ast_test_flag(chan, AST_FLAG_MOH))
01891       ast_moh_stop(chan);
01892  done:
01893    ast_module_user_remove(u);
01894    return res;
01895 }
01896 
01897 static int unload_module(void)
01898 {
01899    int res;
01900 
01901    res = ast_unregister_application(app);
01902    res |= ast_unregister_application(rapp);
01903 
01904    ast_module_user_hangup_all();
01905    
01906    return res;
01907 }
01908 
01909 static int load_module(void)
01910 {
01911    int res;
01912 
01913    res = ast_register_application(app, dial_exec, synopsis, descrip);
01914    res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
01915    
01916    return res;
01917 }
01918 
01919 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing Application");

Generated on Fri Sep 25 19:28:03 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.5