Newer
Older
ast_copy_flags(tmp, &opts,
OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);
ast_copy_string(numsubst, number, sizeof(numsubst));
Mark Spencer
committed
tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
if (!tmp->chan) {
/* If we can't, just go on to the next call */
ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
Mark Spencer
committed
HANDLE_CAUSE(cause, chan);
if (!rest) /* we are on the last destination */
Kevin P. Fleming
committed
chan->hangupcause = cause;
pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
Mark Spencer
committed
if (!ast_strlen_zero(tmp->chan->call_forward)) {
char tmpchan[256];
ast_copy_string(tmpchan, tmp->chan->call_forward, sizeof(tmpchan));
*stuff++ = '\0';
tech = tmpchan;
} else {
snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
stuff = tmpchan;
tech = "Local";
}
tmp->forwards++;
if (tmp->forwards < AST_MAX_FORWARDS) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
ast_hangup(tmp->chan);
/* Setup parameters */
tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
if (!tmp->chan)
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
ast_hangup(tmp->chan);
tmp->chan = NULL;
cause = AST_CAUSE_CONGESTION;
}
if (!tmp->chan) {
Mark Spencer
committed
HANDLE_CAUSE(cause, chan);
continue;
}
/* Setup outgoing SDP to match incoming one */
ast_rtp_make_compatible(tmp->chan, chan);
/* Inherit specially named variables from parent channel */
ast_channel_inherit_variables(chan, tmp->chan);
tmp->chan->appl = "AppDial";
tmp->chan->data = "(Outgoing Line)";
if (tmp->chan->cid.cid_num)
free(tmp->chan->cid.cid_num);
tmp->chan->cid.cid_num = ast_strdup(chan->cid.cid_num);
if (tmp->chan->cid.cid_name)
free(tmp->chan->cid.cid_name);
tmp->chan->cid.cid_name = ast_strdup(chan->cid.cid_name);
if (tmp->chan->cid.cid_ani)
free(tmp->chan->cid.cid_ani);
tmp->chan->cid.cid_ani = ast_strdup(chan->cid.cid_ani);
ast_string_field_set(tmp->chan, language, chan->language);
ast_string_field_set(tmp->chan, accountcode, chan->accountcode);
Mark Spencer
committed
tmp->chan->cdrflags = chan->cdrflags;
Mark Spencer
committed
if (ast_strlen_zero(tmp->chan->musicclass))
ast_string_field_set(tmp->chan, musicclass, chan->musicclass);
/* XXX don't we free previous values ? */
tmp->chan->cid.cid_rdnis = ast_strdup(chan->cid.cid_rdnis);
Martin Pycko
committed
/* Pass callingpres setting */
tmp->chan->cid.cid_pres = chan->cid.cid_pres;
/* Pass type of number */
tmp->chan->cid.cid_ton = chan->cid.cid_ton;
/* Pass type of tns */
tmp->chan->cid.cid_tns = chan->cid.cid_tns;
/* Presense of ADSI CPE on outgoing channel follows ours */
tmp->chan->adsicpe = chan->adsicpe;
/* Pass the transfer capability */
tmp->chan->transfercapability = chan->transfercapability;
/* If we have an outbound group, set this peer channel to it */
if (outbound_group)
ast_app_group_set_channel(tmp->chan, outbound_group);
/* Place the call, but don't wait on the answer */
Martin Pycko
committed
/* Save the info in cdr's that we called them */
if (chan->cdr)
ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
if (res) {
/* Again, keep going even if there's an error */
if (option_debug)
ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
else if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
Mark Spencer
committed
tmp->chan = NULL;
Mark Spencer
committed
} else {
senddialevent(chan, tmp->chan);
ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID))
ast_set_callerid(tmp->chan, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
Mark Spencer
committed
}
/* Put them in the list of outgoing thingies... We're ready now.
XXX If we're forcibly removed, these outgoing calls won't get
hung up XXX */
/* If this line is up, don't try anybody else */
if (outgoing->chan->_state == AST_STATE_UP)
break;
if (ast_strlen_zero(args.timeout)) {
to = -1;
} else {
to = atoi(args.timeout);
if (to > 0)
to *= 1000;
else
ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
if (!outgoing) {
strcpy(status, "CHANUNAVAIL");
} else {
Mark Spencer
committed
/* Our status will at least be NOANSWER */
if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK]);
} else if (ast_test_flag(outgoing, OPT_RINGBACK)) {
ast_indicate(chan, AST_CONTROL_RINGING);
sentringing++;
}
time(&start_time);
peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
if (result) {
res = result;
} else if (to) { /* Musta gotten hung up */
} else { /* Nobody answered, next please? */
res = 0;
/* almost done, although the 'else' block is 400 lines */
} else {
const char *number;
time_t end_time, answer_time = time(NULL);
/* Ah ha! Someone answered within the desired timeframe. Of course after this
we will always return with -1 so that it is hung up properly after the
conversation. */
hanguptree(outgoing, peer);
outgoing = NULL;
/* If appropriate, log that we have a destination channel */
if (chan->cdr)
ast_cdr_setdestchan(chan->cdr, peer->name);
if (peer->name)
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
if (!number)
number = numsubst;
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
if (option_debug)
ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", args.url);
ast_channel_sendurl( peer, args.url );
if ( (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) && privdb_val == AST_PRIVACY_UNKNOWN) {
/* Get the user's intro, store it in priv-callerintros/$CID,
unless it is already there-- this should be done before the
call is actually dialed */
/* all ring indications and moh for the caller has been halted as soon as the
target extension was picked up. We are going to have to kill some
time and make the caller believe the peer hasn't picked up yet */
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
if (ast_test_flag(&opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
ast_indicate(chan, -1);
ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK]);
} else if (ast_test_flag(&opts, OPT_RINGBACK)) {
ast_indicate(chan, AST_CONTROL_RINGING);
sentringing++;
}
/* Start autoservice on the other chan ?? */
res2 = ast_autoservice_start(chan);
/* Now Stream the File */
for (loopcount = 0; loopcount < 3; loopcount++) {
if (res2 && loopcount == 0) /* error in ast_autoservice_start() */
break;
if (!res2) /* on timeout, play the message again */
res2 = ast_play_and_wait(peer,"priv-callpending");
if (!valid_priv_reply(&opts, res2))
res2 = 0;
/* priv-callpending script:
"I have a caller waiting, who introduces themselves as:"
*/
if (!res2)
res2 = ast_play_and_wait(peer,privintro);
if (!valid_priv_reply(&opts, res2))
res2 = 0;
/* now get input from the called party, as to their choice */
if( !res2 ) {
/* XXX can we have both, or they are mutually exclusive ? */
if( ast_test_flag(&opts, OPT_PRIVACY) )
res2 = ast_play_and_wait(peer,"priv-callee-options");
if( ast_test_flag(&opts, OPT_SCREENING) )
res2 = ast_play_and_wait(peer,"screen-callee-options");
}
/*! \page DialPrivacy Dial Privacy scripts
\par priv-callee-options script:
"Dial 1 if you wish this caller to reach you directly in the future,
and immediately connect to their incoming call
Dial 2 if you wish to send this caller to voicemail now and
forevermore.
Dial 3 to send this caller to the torture menus, now and forevermore.
Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
Dial 5 to allow this caller to come straight thru to you in the future,
but right now, just this once, send them to voicemail."
\par screen-callee-options script:
"Dial 1 if you wish to immediately connect to the incoming call
Dial 2 if you wish to send this caller to voicemail.
Dial 3 to send this caller to the torture menus.
Dial 4 to send this caller to a simple "go away" menu.
*/
if (valid_priv_reply(&opts, res2))
break;
/* invalid option */
res2 = ast_play_and_wait(peer, "vm-sorry");
}
if (ast_test_flag(&opts, OPT_MUSICBACK)) {
ast_moh_stop(chan);
} else if (ast_test_flag(&opts, OPT_RINGBACK)) {
ast_indicate(chan, -1);
sentringing=0;
}
ast_autoservice_stop(chan);
switch (res2) {
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
case '1':
if( ast_test_flag(&opts, OPT_PRIVACY) ) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
opt_args[OPT_ARG_PRIVACY], privcid);
ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
}
break;
case '2':
if( ast_test_flag(&opts, OPT_PRIVACY) ) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n",
opt_args[OPT_ARG_PRIVACY], privcid);
ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_DENY);
}
ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
res=0;
goto out;
case '3':
if( ast_test_flag(&opts, OPT_PRIVACY) ) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n",
opt_args[OPT_ARG_PRIVACY], privcid);
ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_TORTURE);
}
ast_copy_string(status, "TORTURE", sizeof(status));
res = 0;
ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
goto out; /* Is this right? */
case '4':
if( ast_test_flag(&opts, OPT_PRIVACY) ) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n",
opt_args[OPT_ARG_PRIVACY], privcid);
ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_KILL);
ast_copy_string(status, "DONTCALL", sizeof(status));
res = 0;
ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
goto out; /* Is this right? */
case '5':
if( ast_test_flag(&opts, OPT_PRIVACY) ) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n",
opt_args[OPT_ARG_PRIVACY], privcid);
ast_privacy_set(opt_args[OPT_ARG_PRIVACY], privcid, AST_PRIVACY_ALLOW);
ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */
res=0;
goto out;
} /* if not privacy, then 5 is the same as "default" case */
default: /* bad input or -1 if failure to start autoservice */
/* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do? */
/* well, there seems basically two choices. Just patch the caller thru immediately,
or,... put 'em thru to voicemail. */
/* since the callee may have hung up, let's do the voicemail thing, no database decision */
ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
res=0;
goto out;
}
/* XXX once again, this path is only taken in the case '1', so it could be
* moved there, although i am not really sure that this is correct - maybe
* the check applies to other cases as well.
*/
/* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll
just clog things up, and it's not useful information, not being tied to a CID */
if( strncmp(privcid,"NOCALLERID",10) == 0 || ast_test_flag(&opts, OPT_SCREEN_NOINTRO) ) {
ast_filedelete(privintro, NULL);
if( ast_fileexists(privintro, NULL, NULL ) > 0 )
ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", privintro);
else if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
}
if (!ast_test_flag(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
res = 0;
} else {
/* Start autoservice on the other chan */
res = ast_autoservice_start(chan);
res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
if (!res) {
digit = ast_waitstream(peer, AST_DIGIT_ANY);
}
res = ast_autoservice_stop(chan);
if (digit > 0 && !res)
res = ast_senddigit(chan, digit);
else
res = digit;
if (chan && peer && ast_test_flag(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
ast_parseable_goto(peer, opt_args[OPT_ARG_GOTO]);
ast_pbx_start(peer);
hanguptree(outgoing, NULL);
res = 0;
goto done;
if (ast_test_flag(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
const char *macro_result;
res = ast_autoservice_start(chan);
if (res) {
ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
res = -1;
}
if (theapp && !res) { /* XXX why check res here ? */
replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
res = 0;
} else {
ast_log(LOG_ERROR, "Could not find application Macro\n");
res = -1;
}
if (ast_autoservice_stop(chan) < 0) {
ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
res = -1;
}
if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
if (!strcasecmp(macro_result, "BUSY")) {
ast_copy_string(status, macro_result, sizeof(status));
Russell Bryant
committed
if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
ast_set_flag(peerflags, OPT_GO_ON);
}
} else
} else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
ast_copy_string(status, macro_result, sizeof(status));
} else if (!strcasecmp(macro_result, "CONTINUE")) {
/* hangup peer and keep chan alive assuming the macro has changed
the context / exten / priority or perhaps
the next priority in the current exten is desired.
*/
res = -1;
} else if (!strcasecmp(macro_result, "ABORT")) {
/* Hangup both ends unless the caller has the g flag */
res = -1;
} else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
res = -1;
/* perform a transfer to a new extension */
if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/
replace_macro_delimiter(macro_transfer_dest);
if (!ast_parseable_goto(chan, macro_transfer_dest))
chan->whentohangup = time(NULL) + calldurationlimit;
if (!ast_strlen_zero(dtmfcalled)) {
ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n", dtmfcalled);
res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
}
if (!ast_strlen_zero(dtmfcalling)) {
ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
}
ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
config.timelimit = timelimit;
config.play_warning = play_warning;
config.warning_freq = warning_freq;
config.warning_sound = warning_sound;
config.end_sound = end_sound;
config.start_sound = start_sound;
if (moh) {
moh = 0;
ast_moh_stop(chan);
} else if (sentringing) {
sentringing = 0;
ast_indicate(chan, -1);
}
Mark Spencer
committed
/* Be sure no generators are left on it */
ast_deactivate_generator(chan);
/* Make sure channels are compatible */
res = ast_channel_make_compatible(chan, peer);
if (res < 0) {
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
ast_hangup(peer);
Mark Spencer
committed
}
if (opermode && (!strncmp(chan->name,"Zap",3)) &&
(!strncmp(peer->name,"Zap",3)))
{
struct oprmode oprmode;
oprmode.peer = peer;
oprmode.mode = opermode;
ast_channel_setoption(chan,
AST_OPTION_OPRMODE,&oprmode,sizeof(struct oprmode),0);
}
time(&end_time);
{
char toast[80];
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
}
} else {
time(&end_time);
{
char toast[80];
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
}
if (res != AST_PBX_NO_HANGUP_PEER) {
if (!chan->_softhangup)
chan->hangupcause = peer->hangupcause;
if (moh) {
moh = 0;
ast_moh_stop(chan);
} else if (sentringing) {
sentringing = 0;
ast_indicate(chan, -1);
}
Mark Spencer
committed
pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
if (option_debug)
ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
Mark Spencer
committed
if ((ast_test_flag(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
done:
Russell Bryant
committed
LOCAL_USER_REMOVE(u);
static int dial_exec(struct ast_channel *chan, void *data)
{
struct ast_flags peerflags;
memset(&peerflags, 0, sizeof(peerflags));
return dial_exec_full(chan, data, &peerflags);
}
static int retrydial_exec(struct ast_channel *chan, void *data)
{
char *announce = NULL, *dialdata = NULL;
const char *context = NULL;
int sleep = 0, loops = 0, res = -1;
Russell Bryant
committed
struct localuser *u;
struct ast_flags peerflags;
if (ast_strlen_zero(data)) {
Russell Bryant
committed
ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
return -1;
}
LOCAL_USER_ADD(u);
Russell Bryant
committed
if (!(announce = ast_strdupa(data)))
goto done;
Russell Bryant
committed
memset(&peerflags, 0, sizeof(peerflags));
if ((dialdata = strchr(announce, '|'))) {
*dialdata++ = '\0';
if ((sleep = atoi(dialdata))) {
sleep *= 1000;
} else {
ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
goto done;
}
if ((dialdata = strchr(dialdata, '|'))) {
*dialdata++ = '\0';
if (!(loops = atoi(dialdata))) {
ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
goto done;
}
}
}
if ((dialdata = strchr(dialdata, '|'))) {
*dialdata++ = '\0';
ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
goto done;
}
if (sleep < 1000)
sleep = 10000;
loops = -1; /* run forever */
context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
res = 0;
while (loops) {
chan->data = "Retrying";
if (ast_test_flag(chan, AST_FLAG_MOH))
ast_moh_stop(chan);
if ((res = dial_exec_full(chan, dialdata, &peerflags)) == 0) {
if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) {
if (!(res = ast_streamfile(chan, announce, chan->language)))
res = ast_waitstream(chan, AST_DIGIT_ANY);
if (!ast_test_flag(chan, AST_FLAG_MOH))
ast_moh_start(chan, NULL);
res = ast_waitfordigit(chan, sleep);
}
} else {
if (!(res = ast_streamfile(chan, announce, chan->language)))
res = ast_waitstream(chan, "");
if (sleep) {
if (!ast_test_flag(chan, AST_FLAG_MOH))
ast_moh_start(chan, NULL);
if (!res)
res = ast_waitfordigit(chan, sleep);
}
}
if (res < 0)
break;
else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
Kevin P. Fleming
committed
if (onedigit_goto(chan, context, (char) res, 1)) {
res = 0;
break;
}
}
loops--;
}
if (loops == 0)
res = 0;
if (ast_test_flag(chan, AST_FLAG_MOH))
ast_moh_stop(chan);
return res;
static int unload_module(void *mod)
Russell Bryant
committed
int res;
res = ast_unregister_application(app);
res |= ast_unregister_application(rapp);
Russell Bryant
committed
return res;
static int load_module(void *mod)
Russell Bryant
committed
res = ast_register_application(app, dial_exec, synopsis, descrip);
res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
static const char *description(void)
return "Dialing Application";
static const char *key(void)
STD_MOD(MOD_1, NULL, NULL, NULL);