Sat Aug 6 00:39:19 2011

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

Generated on Sat Aug 6 00:39:20 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7