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