Mon Mar 31 07:37:54 2008

Asterisk developer's documentation


app_dial.c

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

Generated on Mon Mar 31 07:37:54 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1