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

Generated on Thu Feb 5 16:25:37 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7