Thu May 14 14:48:43 2009

Asterisk developer's documentation


app_dial.c

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

Generated on Thu May 14 14:48:43 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7