Fri Jun 19 12:09:24 2009

Asterisk developer's documentation


app_dial.c

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

Generated on Fri Jun 19 12:09:24 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7