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