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