Fri Aug 24 02:22:09 2007

Asterisk developer's documentation


app_dial.c

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

Generated on Fri Aug 24 02:22:09 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1