Sun Jun 12 16:37:43 2011

Asterisk developer's documentation


app_dial.c

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

Generated on Sun Jun 12 16:37:43 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6