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

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