Tue Mar 2 17:31:42 2010

Asterisk developer's documentation


app_dial.c

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

Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1