Mon May 14 04:42:52 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             strcpy(status, "CANCEL");
00700             if (f)
00701                ast_frfree(f);
00702             return NULL;
00703          }
00704 
00705          if (f && (f->frametype == AST_FRAME_DTMF)) {
00706             if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) {
00707                const char *context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
00708                if (onedigit_goto(in, context, (char) f->subclass, 1)) {
00709                   if (option_verbose > 2)
00710                      ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
00711                   *to=0;
00712                   *result = f->subclass;
00713                   strcpy(status, "CANCEL");
00714                   ast_frfree(f);
00715                   return NULL;
00716                }
00717             }
00718 
00719             if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) && 
00720                     (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
00721                if (option_verbose > 2)
00722                   ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
00723                *to=0;
00724                strcpy(status, "CANCEL");
00725                ast_frfree(f);
00726                return NULL;
00727             }
00728          }
00729 
00730          /* Forward HTML stuff */
00731          if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 
00732             if(ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen) == -1)
00733                ast_log(LOG_WARNING, "Unable to send URL\n");
00734          
00735 
00736          if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END)))  {
00737             if (ast_write(outgoing->chan, f))
00738                ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
00739          }
00740          if (single && (f->frametype == AST_FRAME_CONTROL) && 
00741             ((f->subclass == AST_CONTROL_HOLD) || 
00742              (f->subclass == AST_CONTROL_UNHOLD) || 
00743              (f->subclass == AST_CONTROL_VIDUPDATE))) {
00744             if (option_verbose > 2)
00745                ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
00746             ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen);
00747          }
00748          ast_frfree(f);
00749       }
00750       if (!*to && (option_verbose > 2))
00751          ast_verbose(VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
00752    }
00753 
00754    return peer;
00755 }
00756 
00757 static void replace_macro_delimiter(char *s)
00758 {
00759    for (; *s; s++)
00760       if (*s == '^')
00761          *s = '|';
00762 }
00763 
00764 
00765 /* returns true if there is a valid privacy reply */
00766 static int valid_priv_reply(struct ast_flags *opts, int res)
00767 {
00768    if (res < '1')
00769       return 0;
00770    if (ast_test_flag(opts, OPT_PRIVACY) && res <= '5')
00771       return 1;
00772    if (ast_test_flag(opts, OPT_SCREENING) && res <= '4')
00773       return 1;
00774    return 0;
00775 }
00776 
00777 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags, int *continue_exec)
00778 {
00779    int res = -1;
00780    struct ast_module_user *u;
00781    char *rest, *cur;
00782    struct dial_localuser *outgoing = NULL;
00783    struct ast_channel *peer;
00784    int to;
00785    int numbusy = 0;
00786    int numcongestion = 0;
00787    int numnochan = 0;
00788    int cause;
00789    char numsubst[AST_MAX_EXTENSION];
00790    char cidname[AST_MAX_EXTENSION];
00791    int privdb_val = 0;
00792    unsigned int calldurationlimit = 0;
00793    long timelimit = 0;
00794    long play_warning = 0;
00795    long warning_freq = 0;
00796    const char *warning_sound = NULL;
00797    const char *end_sound = NULL;
00798    const char *start_sound = NULL;
00799    char *dtmfcalled = NULL, *dtmfcalling = NULL;
00800    char status[256] = "INVALIDARGS";
00801    int play_to_caller = 0, play_to_callee = 0;
00802    int sentringing = 0, moh = 0;
00803    const char *outbound_group = NULL;
00804    int result = 0;
00805    time_t start_time;
00806    char privintro[1024];
00807    char privcid[256];
00808    char *parse;
00809    int opermode = 0;
00810    AST_DECLARE_APP_ARGS(args,
00811               AST_APP_ARG(peers);
00812               AST_APP_ARG(timeout);
00813               AST_APP_ARG(options);
00814               AST_APP_ARG(url);
00815    );
00816    struct ast_flags opts = { 0, };
00817    char *opt_args[OPT_ARG_ARRAY_SIZE];
00818 
00819    if (ast_strlen_zero(data)) {
00820       ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
00821       pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
00822       return -1;
00823    }
00824 
00825    u = ast_module_user_add(chan);
00826 
00827    parse = ast_strdupa(data);
00828    
00829    AST_STANDARD_APP_ARGS(args, parse);
00830 
00831    if (!ast_strlen_zero(args.options) &&
00832          ast_app_parse_options(dial_exec_options, &opts, opt_args, args.options)) {
00833       pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
00834       goto done;
00835    }
00836 
00837    if (ast_strlen_zero(args.peers)) {
00838       ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
00839       pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
00840       goto done;
00841    }
00842 
00843    if (ast_test_flag(&opts, OPT_OPERMODE)) {
00844       if (ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]))
00845          opermode = 1;
00846       else opermode = atoi(opt_args[OPT_ARG_OPERMODE]);
00847       if (option_verbose > 2)
00848          ast_verbose(VERBOSE_PREFIX_3 "Setting operator services mode to %d.\n", opermode);
00849    }
00850    
00851    if (ast_test_flag(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
00852       calldurationlimit = atoi(opt_args[OPT_ARG_DURATION_STOP]);
00853       if (!calldurationlimit) {
00854          ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
00855          pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
00856          goto done;
00857       }
00858       if (option_verbose > 2)
00859          ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
00860    }
00861 
00862    if (ast_test_flag(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
00863       dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
00864       dtmfcalled = strsep(&dtmfcalling, ":");
00865    }
00866 
00867    if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
00868       char *limit_str, *warning_str, *warnfreq_str;
00869       const char *var;
00870 
00871       warnfreq_str = opt_args[OPT_ARG_DURATION_LIMIT];
00872       limit_str = strsep(&warnfreq_str, ":");
00873       warning_str = strsep(&warnfreq_str, ":");
00874 
00875       timelimit = atol(limit_str);
00876       if (warning_str)
00877          play_warning = atol(warning_str);
00878       if (warnfreq_str)
00879          warning_freq = atol(warnfreq_str);
00880 
00881       if (!timelimit) {
00882          ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
00883          goto done;
00884       } else if (play_warning > timelimit) {
00885          /* If the first warning is requested _after_ the entire call would end,
00886             and no warning frequency is requested, then turn off the warning. If
00887             a warning frequency is requested, reduce the 'first warning' time by
00888             that frequency until it falls within the call's total time limit.
00889          */
00890 
00891          if (!warning_freq) {
00892             play_warning = 0;
00893          } else {
00894             /* XXX fix this!! */
00895             while (play_warning > timelimit)
00896                play_warning -= warning_freq;
00897             if (play_warning < 1)
00898                play_warning = warning_freq = 0;
00899          }
00900       }
00901 
00902       var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
00903       play_to_caller = var ? ast_true(var) : 1;
00904       
00905       var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
00906       play_to_callee = var ? ast_true(var) : 0;
00907       
00908       if (!play_to_caller && !play_to_callee)
00909          play_to_caller = 1;
00910       
00911       var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
00912       warning_sound = S_OR(var, "timeleft");
00913       
00914       var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
00915       end_sound = S_OR(var, NULL);  /* XXX not much of a point in doing this! */
00916       
00917       var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
00918       start_sound = S_OR(var, NULL);   /* XXX not much of a point in doing this! */
00919 
00920       /* undo effect of S(x) in case they are both used */
00921       calldurationlimit = 0;
00922       /* more efficient to do it like S(x) does since no advanced opts */
00923       if (!play_warning && !start_sound && !end_sound && timelimit) {
00924          calldurationlimit = timelimit / 1000;
00925          if (option_verbose > 2)
00926             ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
00927          timelimit = play_to_caller = play_to_callee = play_warning = warning_freq = 0;
00928       } else if (option_verbose > 2) {
00929          ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n");
00930          ast_verbose(VERBOSE_PREFIX_4 "timelimit      = %ld\n", timelimit);
00931          ast_verbose(VERBOSE_PREFIX_4 "play_warning   = %ld\n", play_warning);
00932          ast_verbose(VERBOSE_PREFIX_4 "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
00933          ast_verbose(VERBOSE_PREFIX_4 "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
00934          ast_verbose(VERBOSE_PREFIX_4 "warning_freq   = %ld\n", warning_freq);
00935          ast_verbose(VERBOSE_PREFIX_4 "start_sound    = %s\n", start_sound);
00936          ast_verbose(VERBOSE_PREFIX_4 "warning_sound  = %s\n", warning_sound);
00937          ast_verbose(VERBOSE_PREFIX_4 "end_sound      = %s\n", end_sound);
00938       }
00939    }
00940 
00941    if (ast_test_flag(&opts, OPT_RESETCDR) && chan->cdr)
00942       ast_cdr_reset(chan->cdr, NULL);
00943    if (ast_test_flag(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
00944       opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
00945    if (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) {
00946       char callerid[60];
00947       char *l = chan->cid.cid_num;  /* XXX watch out, we are overwriting it */
00948       if (!ast_strlen_zero(l)) {
00949          ast_shrink_phone_number(l);
00950          if( ast_test_flag(&opts, OPT_PRIVACY) ) {
00951             if (option_verbose > 2)
00952                ast_verbose(VERBOSE_PREFIX_3  "Privacy DB is '%s', clid is '%s'\n",
00953                        opt_args[OPT_ARG_PRIVACY], l);
00954             privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
00955          }
00956          else {
00957             if (option_verbose > 2)
00958                ast_verbose(VERBOSE_PREFIX_3  "Privacy Screening, clid is '%s'\n", l);
00959             privdb_val = AST_PRIVACY_UNKNOWN;
00960          }
00961       } else {
00962          char *tnam, *tn2;
00963 
00964          tnam = ast_strdupa(chan->name);
00965          /* clean the channel name so slashes don't try to end up in disk file name */
00966          for(tn2 = tnam; *tn2; tn2++) {
00967             if( *tn2=='/')
00968                *tn2 = '=';  /* any other chars to be afraid of? */
00969          }
00970          if (option_verbose > 2)
00971             ast_verbose(VERBOSE_PREFIX_3  "Privacy-- callerid is empty\n");
00972 
00973          snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
00974          l = callerid;
00975          privdb_val = AST_PRIVACY_UNKNOWN;
00976       }
00977       
00978       ast_copy_string(privcid,l,sizeof(privcid));
00979 
00980       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 */  
00981          if (option_verbose > 2)
00982             ast_verbose( VERBOSE_PREFIX_3  "CallerID set (%s); N option set; Screening should be off\n", privcid);
00983          privdb_val = AST_PRIVACY_ALLOW;
00984       }
00985       else if(ast_test_flag(&opts, OPT_SCREEN_NOCLID) && strncmp(privcid,"NOCALLERID",10) == 0 ) {
00986          if (option_verbose > 2)
00987             ast_verbose( VERBOSE_PREFIX_3  "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val);
00988       }
00989       
00990       if(privdb_val == AST_PRIVACY_DENY ) {
00991          ast_copy_string(status, "NOANSWER", sizeof(status));
00992          if (option_verbose > 2)
00993             ast_verbose( VERBOSE_PREFIX_3  "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
00994          res=0;
00995          goto out;
00996       }
00997       else if(privdb_val == AST_PRIVACY_KILL ) {
00998          ast_copy_string(status, "DONTCALL", sizeof(status));
00999          if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
01000             ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
01001          }
01002          res = 0;
01003          goto out; /* Is this right? */
01004       }
01005       else if(privdb_val == AST_PRIVACY_TORTURE ) {
01006          ast_copy_string(status, "TORTURE", sizeof(status));
01007          if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
01008             ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
01009          }
01010          res = 0;
01011          goto out; /* is this right??? */
01012       }
01013       else if(privdb_val == AST_PRIVACY_UNKNOWN ) {
01014          /* Get the user's intro, store it in priv-callerintros/$CID, 
01015             unless it is already there-- this should be done before the 
01016             call is actually dialed  */
01017 
01018          /* make sure the priv-callerintros dir actually exists */
01019          snprintf(privintro, sizeof(privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
01020          if (mkdir(privintro, 0755) && errno != EEXIST) {
01021             ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(errno));
01022             res = -1;
01023             goto out;
01024          }
01025 
01026          snprintf(privintro,sizeof(privintro), "priv-callerintros/%s", privcid);
01027          if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) {
01028             /* the DELUX version of this code would allow this caller the
01029                option to hear and retape their previously recorded intro.
01030             */
01031          }
01032          else {
01033             int duration; /* for feedback from play_and_wait */
01034             /* the file doesn't exist yet. Let the caller submit his
01035                vocal intro for posterity */
01036             /* priv-recordintro script:
01037 
01038                "At the tone, please say your name:"
01039 
01040             */
01041             ast_answer(chan);
01042             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 */
01043                               /* don't think we'll need a lock removed, we took care of
01044                                  conflicts by naming the privintro file */
01045             if (res == -1) {
01046                /* Delete the file regardless since they hung up during recording */
01047                                         ast_filedelete(privintro, NULL);
01048                                         if( ast_fileexists(privintro,NULL,NULL ) > 0 )
01049                                                 ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro);
01050                                         else if (option_verbose > 2)
01051                                                 ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
01052                goto out;
01053             }
01054                                 if( !ast_streamfile(chan, "vm-dialout", chan->language) )
01055                                         ast_waitstream(chan, "");
01056          }
01057       }
01058    }
01059 
01060    if (continue_exec)
01061       *continue_exec = 0;
01062    
01063    /* If a channel group has been specified, get it for use when we create peer channels */
01064    if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) {
01065       outbound_group = ast_strdupa(outbound_group);
01066       pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL);
01067    } else {
01068       outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
01069    }
01070        
01071    ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
01072    /* loop through the list of dial destinations */
01073    rest = args.peers;
01074    while ((cur = strsep(&rest, "&")) ) {
01075       struct dial_localuser *tmp;
01076       /* Get a technology/[device:]number pair */
01077       char *number = cur;
01078       char *tech = strsep(&number, "/");
01079       if (!number) {
01080          ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
01081          goto out;
01082       }
01083       if (!(tmp = ast_calloc(1, sizeof(*tmp))))
01084          goto out;
01085       if (opts.flags) {
01086          ast_copy_flags(tmp, &opts,
01087                    OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
01088                    OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
01089                    OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
01090                    OPT_CALLEE_PARK | OPT_CALLER_PARK |
01091                    OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
01092          ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);  
01093       }
01094       ast_copy_string(numsubst, number, sizeof(numsubst));
01095       /* Request the peer */
01096       tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
01097       if (!tmp->chan) {
01098          /* If we can't, just go on to the next call */
01099          ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
01100          HANDLE_CAUSE(cause, chan);
01101          if (!rest)  /* we are on the last destination */
01102             chan->hangupcause = cause;
01103          free(tmp);
01104          continue;
01105       }
01106       pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
01107       if (!ast_strlen_zero(tmp->chan->call_forward)) {
01108          char tmpchan[256];
01109          char *stuff;
01110          char *tech;
01111          ast_copy_string(tmpchan, tmp->chan->call_forward, sizeof(tmpchan));
01112          if ((stuff = strchr(tmpchan, '/'))) {
01113             *stuff++ = '\0';
01114             tech = tmpchan;
01115          } else {
01116             snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
01117             stuff = tmpchan;
01118             tech = "Local";
01119          }
01120          tmp->forwards++;
01121          if (tmp->forwards < AST_MAX_FORWARDS) {
01122             if (option_verbose > 2)
01123                ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
01124             ast_hangup(tmp->chan);
01125             /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
01126             if (ast_test_flag(&opts, OPT_IGNORE_FORWARDING)) {
01127                tmp->chan = NULL;
01128                cause = AST_CAUSE_BUSY;
01129                if (option_verbose > 2)
01130                   ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", chan->name, tech, stuff);
01131             } else {
01132                tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
01133             }
01134             if (!tmp->chan)
01135                ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
01136             else
01137                ast_channel_inherit_variables(chan, tmp->chan);
01138          } else {
01139             if (option_verbose > 2)
01140                ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
01141             ast_hangup(tmp->chan);
01142             tmp->chan = NULL;
01143             cause = AST_CAUSE_CONGESTION;
01144          }
01145          if (!tmp->chan) {
01146             HANDLE_CAUSE(cause, chan);
01147             free(tmp);
01148             continue;
01149          }
01150       }
01151 
01152       /* Setup outgoing SDP to match incoming one */
01153       ast_rtp_make_compatible(tmp->chan, chan, !outgoing && !rest);
01154       
01155       /* Inherit specially named variables from parent channel */
01156       ast_channel_inherit_variables(chan, tmp->chan);
01157 
01158       tmp->chan->appl = "AppDial";
01159       tmp->chan->data = "(Outgoing Line)";
01160       tmp->chan->whentohangup = 0;
01161 
01162       if (tmp->chan->cid.cid_num)
01163          free(tmp->chan->cid.cid_num);
01164       tmp->chan->cid.cid_num = ast_strdup(chan->cid.cid_num);
01165 
01166       if (tmp->chan->cid.cid_name)
01167          free(tmp->chan->cid.cid_name);
01168       tmp->chan->cid.cid_name = ast_strdup(chan->cid.cid_name);
01169 
01170       if (tmp->chan->cid.cid_ani)
01171          free(tmp->chan->cid.cid_ani);
01172       tmp->chan->cid.cid_ani = ast_strdup(chan->cid.cid_ani);
01173       
01174       if (tmp->chan->cid.cid_dnid)
01175          free(tmp->chan->cid.cid_dnid);
01176       
01177       tmp->chan->cid.cid_dnid = ast_strdup(chan->cid.cid_dnid);
01178 
01179       /* Copy language from incoming to outgoing */
01180       ast_string_field_set(tmp->chan, language, chan->language);
01181       ast_string_field_set(tmp->chan, accountcode, chan->accountcode);
01182       tmp->chan->cdrflags = chan->cdrflags;
01183       if (ast_strlen_zero(tmp->chan->musicclass))
01184          ast_string_field_set(tmp->chan, musicclass, chan->musicclass);
01185       /* XXX don't we free previous values ? */
01186       tmp->chan->cid.cid_rdnis = ast_strdup(chan->cid.cid_rdnis);
01187       /* Pass callingpres setting */
01188       tmp->chan->cid.cid_pres = chan->cid.cid_pres;
01189       /* Pass type of number */
01190       tmp->chan->cid.cid_ton = chan->cid.cid_ton;
01191       /* Pass type of tns */
01192       tmp->chan->cid.cid_tns = chan->cid.cid_tns;
01193       /* Presense of ADSI CPE on outgoing channel follows ours */
01194       tmp->chan->adsicpe = chan->adsicpe;
01195       /* Pass the transfer capability */
01196       tmp->chan->transfercapability = chan->transfercapability;
01197 
01198       /* If we have an outbound group, set this peer channel to it */
01199       if (outbound_group)
01200          ast_app_group_set_channel(tmp->chan, outbound_group);
01201 
01202       /* Inherit context and extension */
01203       if (!ast_strlen_zero(chan->macrocontext))
01204          ast_copy_string(tmp->chan->dialcontext, chan->macrocontext, sizeof(tmp->chan->dialcontext));
01205       else
01206          ast_copy_string(tmp->chan->dialcontext, chan->context, sizeof(tmp->chan->dialcontext));
01207       if (!ast_strlen_zero(chan->macroexten))
01208          ast_copy_string(tmp->chan->exten, chan->macroexten, sizeof(tmp->chan->exten));
01209       else
01210          ast_copy_string(tmp->chan->exten, chan->exten, sizeof(tmp->chan->exten));
01211 
01212       /* Place the call, but don't wait on the answer */
01213       res = ast_call(tmp->chan, numsubst, 0);
01214 
01215       /* Save the info in cdr's that we called them */
01216       if (chan->cdr)
01217          ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
01218 
01219       /* check the results of ast_call */
01220       if (res) {
01221          /* Again, keep going even if there's an error */
01222          if (option_debug)
01223             ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
01224          if (option_verbose > 2)
01225             ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
01226          ast_hangup(tmp->chan);
01227          tmp->chan = NULL;
01228          free(tmp);
01229          continue;
01230       } else {
01231          senddialevent(chan, tmp->chan);
01232          if (option_verbose > 2)
01233             ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
01234          if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID))
01235             ast_set_callerid(tmp->chan, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
01236       }
01237       /* Put them in the list of outgoing thingies...  We're ready now. 
01238          XXX If we're forcibly removed, these outgoing calls won't get
01239          hung up XXX */
01240       ast_set_flag(tmp, DIAL_STILLGOING); 
01241       tmp->next = outgoing;
01242       outgoing = tmp;
01243       /* If this line is up, don't try anybody else */
01244       if (outgoing->chan->_state == AST_STATE_UP)
01245          break;
01246    }
01247    
01248    if (ast_strlen_zero(args.timeout)) {
01249       to = -1;
01250    } else {
01251       to = atoi(args.timeout);
01252       if (to > 0)
01253          to *= 1000;
01254       else
01255          ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
01256    }
01257 
01258    if (!outgoing) {
01259       strcpy(status, "CHANUNAVAIL");
01260    } else {
01261       /* Our status will at least be NOANSWER */
01262       strcpy(status, "NOANSWER");
01263       if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
01264          moh = 1;
01265          if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01266             char *original_moh = ast_strdupa(chan->musicclass);
01267             ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01268             ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01269             ast_string_field_set(chan, musicclass, original_moh);
01270          } else {
01271             ast_moh_start(chan, NULL, NULL);
01272          }
01273          ast_indicate(chan, AST_CONTROL_PROGRESS);
01274       } else if (ast_test_flag(outgoing, OPT_RINGBACK)) {
01275          ast_indicate(chan, AST_CONTROL_RINGING);
01276          sentringing++;
01277       }
01278    }
01279 
01280    time(&start_time);
01281    peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
01282    
01283    if (!peer) {
01284       if (result) {
01285          res = result;
01286       } else if (to) { /* Musta gotten hung up */
01287          res = -1;
01288       } else { /* Nobody answered, next please? */
01289          res = 0;
01290       }
01291       /* almost done, although the 'else' block is 400 lines */
01292    } else {
01293       const char *number;
01294       time_t end_time, answer_time = time(NULL);
01295 
01296       strcpy(status, "ANSWER");
01297       /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
01298          we will always return with -1 so that it is hung up properly after the 
01299          conversation.  */
01300       hanguptree(outgoing, peer);
01301       outgoing = NULL;
01302       /* If appropriate, log that we have a destination channel */
01303       if (chan->cdr)
01304          ast_cdr_setdestchan(chan->cdr, peer->name);
01305       if (peer->name)
01306          pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
01307 
01308       number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
01309       if (!number)
01310          number = numsubst;
01311       pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
01312       if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
01313          if (option_debug)
01314             ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", args.url);
01315          ast_channel_sendurl( peer, args.url );
01316       }
01317       if ( (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) && privdb_val == AST_PRIVACY_UNKNOWN) {
01318          int res2;
01319          int loopcount = 0;
01320 
01321          /* Get the user's intro, store it in priv-callerintros/$CID, 
01322             unless it is already there-- this should be done before the 
01323             call is actually dialed  */
01324 
01325          /* all ring indications and moh for the caller has been halted as soon as the 
01326             target extension was picked up. We are going to have to kill some
01327             time and make the caller believe the peer hasn't picked up yet */
01328 
01329          if (ast_test_flag(&opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01330             char *original_moh = ast_strdupa(chan->musicclass);
01331             ast_indicate(chan, -1);
01332             ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01333             ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01334             ast_string_field_set(chan, musicclass, original_moh);
01335          } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
01336             ast_indicate(chan, AST_CONTROL_RINGING);
01337             sentringing++;
01338          }
01339 
01340          /* Start autoservice on the other chan ?? */
01341          res2 = ast_autoservice_start(chan);
01342          /* Now Stream the File */
01343          for (loopcount = 0; loopcount < 3; loopcount++) {
01344             if (res2 && loopcount == 0)   /* error in ast_autoservice_start() */
01345                break;
01346             if (!res2)  /* on timeout, play the message again */
01347                res2 = ast_play_and_wait(peer,"priv-callpending");
01348             if (!valid_priv_reply(&opts, res2))
01349                res2 = 0;
01350             /* priv-callpending script: 
01351                "I have a caller waiting, who introduces themselves as:"
01352             */
01353             if (!res2)
01354                res2 = ast_play_and_wait(peer,privintro);
01355             if (!valid_priv_reply(&opts, res2))
01356                res2 = 0;
01357             /* now get input from the called party, as to their choice */
01358             if( !res2 ) {
01359                /* XXX can we have both, or they are mutually exclusive ? */
01360                if( ast_test_flag(&opts, OPT_PRIVACY) )
01361                   res2 = ast_play_and_wait(peer,"priv-callee-options");
01362                if( ast_test_flag(&opts, OPT_SCREENING) )
01363                   res2 = ast_play_and_wait(peer,"screen-callee-options");
01364             }
01365             /*! \page DialPrivacy Dial Privacy scripts
01366             \par priv-callee-options script:
01367                "Dial 1 if you wish this caller to reach you directly in the future,
01368                   and immediately connect to their incoming call
01369                 Dial 2 if you wish to send this caller to voicemail now and 
01370                   forevermore.
01371                 Dial 3 to send this caller to the torture menus, now and forevermore.
01372                 Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
01373                 Dial 5 to allow this caller to come straight thru to you in the future,
01374                   but right now, just this once, send them to voicemail."
01375             \par screen-callee-options script:
01376                "Dial 1 if you wish to immediately connect to the incoming call
01377                 Dial 2 if you wish to send this caller to voicemail.
01378                 Dial 3 to send this caller to the torture menus.
01379                 Dial 4 to send this caller to a simple "go away" menu.
01380             */
01381             if (valid_priv_reply(&opts, res2))
01382                break;
01383             /* invalid option */
01384             res2 = ast_play_and_wait(peer, "vm-sorry");
01385          }
01386 
01387          if (ast_test_flag(&opts, OPT_MUSICBACK)) {
01388             ast_moh_stop(chan);
01389          } else if (ast_test_flag(&opts, OPT_RINGBACK)) {
01390             ast_indicate(chan, -1);
01391             sentringing=0;
01392          }
01393          ast_autoservice_stop(chan);
01394 
01395          switch (res2) {
01396          case '1':
01397             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01398                if (option_verbose > 2)
01399                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
01400                           opt_args[OPT_ARG_PRIVACY], privcid);
01401                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
01402             }
01403             break;
01404          case '2':
01405             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01406                if (option_verbose > 2)
01407                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n",
01408                           opt_args[OPT_ARG_PRIVACY], privcid);
01409                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
01410             }
01411             ast_copy_string(status, "NOANSWER", sizeof(status));
01412             ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
01413             res=0;
01414             goto out;
01415          case '3':
01416             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01417                if (option_verbose > 2)
01418                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n",
01419                           opt_args[OPT_ARG_PRIVACY], privcid);
01420                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_TORTURE);
01421             }
01422             ast_copy_string(status, "TORTURE", sizeof(status));
01423             
01424             res = 0;
01425             ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
01426             goto out; /* Is this right? */
01427          case '4':
01428             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01429                if (option_verbose > 2)
01430                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n",
01431                           opt_args[OPT_ARG_PRIVACY], privcid);
01432                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_KILL);
01433             }
01434 
01435             ast_copy_string(status, "DONTCALL", sizeof(status));
01436             res = 0;
01437             ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
01438             goto out; /* Is this right? */
01439          case '5':
01440             if( ast_test_flag(&opts, OPT_PRIVACY) ) {
01441                if (option_verbose > 2)
01442                   ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
01443                           opt_args[OPT_ARG_PRIVACY], privcid);
01444                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
01445                ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
01446                res=0;
01447                goto out;
01448             } /* if not privacy, then 5 is the same as "default" case */
01449          default: /* bad input or -1 if failure to start autoservice */
01450             /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do?  */
01451             /* well, there seems basically two choices. Just patch the caller thru immediately,
01452                  or,... put 'em thru to voicemail. */
01453             /* since the callee may have hung up, let's do the voicemail thing, no database decision */
01454             ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
01455             ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
01456             res=0;
01457             goto out;
01458          }
01459 
01460          /* XXX once again, this path is only taken in the case '1', so it could be
01461           * moved there, although i am not really sure that this is correct - maybe
01462           * the check applies to other cases as well.
01463           */
01464          /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll 
01465             just clog things up, and it's not useful information, not being tied to a CID */
01466          if( strncmp(privcid,"NOCALLERID",10) == 0 || ast_test_flag(&opts, OPT_SCREEN_NOINTRO) ) {
01467             ast_filedelete(privintro, NULL);
01468             if( ast_fileexists(privintro, NULL, NULL ) > 0 )
01469                ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", privintro);
01470             else if (option_verbose > 2)
01471                ast_verbose(VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
01472          }
01473       }
01474       if (!ast_test_flag(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
01475          res = 0;
01476       } else {
01477          int digit = 0;
01478          /* Start autoservice on the other chan */
01479          res = ast_autoservice_start(chan);
01480          /* Now Stream the File */
01481          if (!res)
01482             res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
01483          if (!res) {
01484             digit = ast_waitstream(peer, AST_DIGIT_ANY); 
01485          }
01486          /* Ok, done. stop autoservice */
01487          res = ast_autoservice_stop(chan);
01488          if (digit > 0 && !res)
01489             res = ast_senddigit(chan, digit); 
01490          else
01491             res = digit;
01492 
01493       }
01494 
01495       if (chan && peer && ast_test_flag(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
01496          replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
01497          ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
01498          ast_parseable_goto(peer, opt_args[OPT_ARG_GOTO]);
01499          peer->priority++;
01500          ast_pbx_start(peer);
01501          hanguptree(outgoing, NULL);
01502          if (continue_exec)
01503             *continue_exec = 1;
01504          res = 0;
01505          goto done;
01506       }
01507 
01508       if (ast_test_flag(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
01509          struct ast_app *theapp;
01510          const char *macro_result;
01511 
01512          res = ast_autoservice_start(chan);
01513          if (res) {
01514             ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
01515             res = -1;
01516          }
01517 
01518          theapp = pbx_findapp("Macro");
01519 
01520          if (theapp && !res) {   /* XXX why check res here ? */
01521             replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
01522             res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
01523             ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
01524             res = 0;
01525          } else {
01526             ast_log(LOG_ERROR, "Could not find application Macro\n");
01527             res = -1;
01528          }
01529 
01530          if (ast_autoservice_stop(chan) < 0) {
01531             ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
01532             res = -1;
01533          }
01534 
01535          if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
01536                char *macro_transfer_dest;
01537 
01538                if (!strcasecmp(macro_result, "BUSY")) {
01539                   ast_copy_string(status, macro_result, sizeof(status));
01540                   if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
01541                      if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
01542                         ast_set_flag(peerflags, OPT_GO_ON);
01543                      }
01544                   } else
01545                      ast_set_flag(peerflags, OPT_GO_ON);
01546                   res = -1;
01547                } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
01548                   ast_copy_string(status, macro_result, sizeof(status));
01549                   ast_set_flag(peerflags, OPT_GO_ON); 
01550                   res = -1;
01551                } else if (!strcasecmp(macro_result, "CONTINUE")) {
01552                   /* hangup peer and keep chan alive assuming the macro has changed 
01553                      the context / exten / priority or perhaps 
01554                      the next priority in the current exten is desired.
01555                   */
01556                   ast_set_flag(peerflags, OPT_GO_ON); 
01557                   res = -1;
01558                } else if (!strcasecmp(macro_result, "ABORT")) {
01559                   /* Hangup both ends unless the caller has the g flag */
01560                   res = -1;
01561                } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
01562                   res = -1;
01563                   /* perform a transfer to a new extension */
01564                   if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/
01565                      replace_macro_delimiter(macro_transfer_dest);
01566                      if (!ast_parseable_goto(chan, macro_transfer_dest))
01567                         ast_set_flag(peerflags, OPT_GO_ON);
01568 
01569                   }
01570                }
01571          }
01572       }
01573 
01574       if (!res) {
01575          if (calldurationlimit > 0) {
01576             chan->whentohangup = time(NULL) + calldurationlimit;
01577          }
01578          if (!ast_strlen_zero(dtmfcalled)) { 
01579             if (option_verbose > 2)
01580                ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n", dtmfcalled);
01581             res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
01582          }
01583          if (!ast_strlen_zero(dtmfcalling)) {
01584             if (option_verbose > 2)
01585                ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
01586             res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
01587          }
01588       }
01589       
01590       if (!res) {
01591          struct ast_bridge_config config;
01592 
01593          memset(&config,0,sizeof(struct ast_bridge_config));
01594          if (play_to_caller)
01595             ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
01596          if (play_to_callee)
01597             ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
01598          if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
01599             ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
01600          if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
01601             ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
01602          if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
01603             ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
01604          if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
01605             ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
01606          if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
01607             ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
01608          if (ast_test_flag(peerflags, OPT_CALLER_MONITOR)) 
01609             ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
01610          if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
01611             ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
01612          if (ast_test_flag(peerflags, OPT_CALLER_PARK))
01613             ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
01614 
01615          config.timelimit = timelimit;
01616          config.play_warning = play_warning;
01617          config.warning_freq = warning_freq;
01618          config.warning_sound = warning_sound;
01619          config.end_sound = end_sound;
01620          config.start_sound = start_sound;
01621          if (moh) {
01622             moh = 0;
01623             ast_moh_stop(chan);
01624          } else if (sentringing) {
01625             sentringing = 0;
01626             ast_indicate(chan, -1);
01627          }
01628          /* Be sure no generators are left on it */
01629          ast_deactivate_generator(chan);
01630          /* Make sure channels are compatible */
01631          res = ast_channel_make_compatible(chan, peer);
01632          if (res < 0) {
01633             ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
01634             ast_hangup(peer);
01635             res = -1;
01636             goto done;
01637          }
01638          if (opermode && (!strncmp(chan->name,"Zap",3)) &&
01639             (!strncmp(peer->name,"Zap",3)))
01640          {
01641             struct oprmode oprmode;
01642 
01643             oprmode.peer = peer;
01644             oprmode.mode = opermode;
01645 
01646             ast_channel_setoption(chan,
01647                AST_OPTION_OPRMODE,&oprmode,sizeof(struct oprmode),0);
01648          }
01649          res = ast_bridge_call(chan,peer,&config);
01650          time(&end_time);
01651          {
01652             char toast[80];
01653             snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
01654             pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
01655          }
01656       } else {
01657          time(&end_time);
01658          res = -1;
01659       }
01660       {
01661          char toast[80];
01662          snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
01663          pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
01664       }
01665       
01666       if (res != AST_PBX_NO_HANGUP_PEER) {
01667          if (!chan->_softhangup)
01668             chan->hangupcause = peer->hangupcause;
01669          ast_hangup(peer);
01670       }
01671    }  
01672 out:
01673    if (moh) {
01674       moh = 0;
01675       ast_moh_stop(chan);
01676    } else if (sentringing) {
01677       sentringing = 0;
01678       ast_indicate(chan, -1);
01679    }
01680    ast_rtp_early_bridge(chan, NULL);
01681    hanguptree(outgoing, NULL);
01682    pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
01683    if (option_debug)
01684       ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
01685    
01686    if ((ast_test_flag(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
01687       res = 0;
01688 
01689 done:
01690    ast_module_user_remove(u);    
01691    return res;
01692 }
01693 
01694 static int dial_exec(struct ast_channel *chan, void *data)
01695 {
01696    struct ast_flags peerflags;
01697 
01698    memset(&peerflags, 0, sizeof(peerflags));
01699 
01700    return dial_exec_full(chan, data, &peerflags, NULL);
01701 }
01702 
01703 static int retrydial_exec(struct ast_channel *chan, void *data)
01704 {
01705    char *announce = NULL, *dialdata = NULL;
01706    const char *context = NULL;
01707    int sleep = 0, loops = 0, res = -1;
01708    struct ast_module_user *u;
01709    struct ast_flags peerflags;
01710    
01711    if (ast_strlen_zero(data)) {
01712       ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
01713       return -1;
01714    }  
01715 
01716    u = ast_module_user_add(chan);
01717 
01718    announce = ast_strdupa(data);
01719 
01720    memset(&peerflags, 0, sizeof(peerflags));
01721 
01722    if ((dialdata = strchr(announce, '|'))) {
01723       *dialdata++ = '\0';
01724       if ((sleep = atoi(dialdata))) {
01725          sleep *= 1000;
01726       } else {
01727          ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
01728          goto done;
01729       }
01730       if ((dialdata = strchr(dialdata, '|'))) {
01731          *dialdata++ = '\0';
01732          if (!(loops = atoi(dialdata))) {
01733             ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
01734             goto done;
01735          }
01736       }
01737    }
01738    
01739    if ((dialdata = strchr(dialdata, '|'))) {
01740       *dialdata++ = '\0';
01741    } else {
01742       ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
01743       goto done;
01744    }
01745       
01746    if (sleep < 1000)
01747       sleep = 10000;
01748 
01749    if (!loops)
01750       loops = -1; /* run forever */
01751    
01752    context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
01753 
01754    res = 0;
01755    while (loops) {
01756       int continue_exec;
01757 
01758       chan->data = "Retrying";
01759       if (ast_test_flag(chan, AST_FLAG_MOH))
01760          ast_moh_stop(chan);
01761 
01762       res = dial_exec_full(chan, dialdata, &peerflags, &continue_exec);
01763       if (continue_exec)
01764          break;
01765       if (res == 0) {
01766          if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) {
01767             if (!(res = ast_streamfile(chan, announce, chan->language)))
01768                res = ast_waitstream(chan, AST_DIGIT_ANY);
01769             if (!res && sleep) {
01770                if (!ast_test_flag(chan, AST_FLAG_MOH))
01771                   ast_moh_start(chan, NULL, NULL);
01772                res = ast_waitfordigit(chan, sleep);
01773             }
01774          } else {
01775             if (!(res = ast_streamfile(chan, announce, chan->language)))
01776                res = ast_waitstream(chan, "");
01777             if (sleep) {
01778                if (!ast_test_flag(chan, AST_FLAG_MOH))
01779                   ast_moh_start(chan, NULL, NULL);
01780                if (!res) 
01781                   res = ast_waitfordigit(chan, sleep);
01782             }
01783          }
01784       }
01785 
01786       if (res < 0)
01787          break;
01788       else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
01789          if (onedigit_goto(chan, context, (char) res, 1)) {
01790             res = 0;
01791             break;
01792          }
01793       }
01794       loops--;
01795    }
01796    if (loops == 0)
01797       res = 0;
01798    else if (res == 1)
01799       res = 0;
01800 
01801    if (ast_test_flag(chan, AST_FLAG_MOH))
01802       ast_moh_stop(chan);
01803  done:
01804    ast_module_user_remove(u);
01805    return res;
01806 }
01807 
01808 static int unload_module(void)
01809 {
01810    int res;
01811 
01812    res = ast_unregister_application(app);
01813    res |= ast_unregister_application(rapp);
01814 
01815    ast_module_user_hangup_all();
01816    
01817    return res;
01818 }
01819 
01820 static int load_module(void)
01821 {
01822    int res;
01823 
01824    res = ast_register_application(app, dial_exec, synopsis, descrip);
01825    res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
01826    
01827    return res;
01828 }
01829 
01830 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing Application");

Generated on Mon May 14 04:42:52 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1