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