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

Generated on Wed Oct 28 11:45:25 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6