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