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: 73052 $")
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_SEND