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