[asterisk-commits] oej: branch oej/codename-pineapple r47362 - in
/team/oej/codename-pineapple: ...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Nov 9 06:44:10 MST 2006
Author: oej
Date: Thu Nov 9 07:44:09 2006
New Revision: 47362
URL: http://svn.digium.com/view/asterisk?view=rev&rev=47362
Log:
update
Removed:
team/oej/codename-pineapple/aclocal.m4
Modified:
team/oej/codename-pineapple/apps/app_dial.c
team/oej/codename-pineapple/apps/app_queue.c
team/oej/codename-pineapple/apps/app_voicemail.c
team/oej/codename-pineapple/channels/Makefile
team/oej/codename-pineapple/channels/chan_agent.c
team/oej/codename-pineapple/channels/chan_alsa.c
team/oej/codename-pineapple/channels/chan_features.c
team/oej/codename-pineapple/channels/chan_gtalk.c
team/oej/codename-pineapple/channels/chan_h323.c
team/oej/codename-pineapple/channels/chan_iax2.c
team/oej/codename-pineapple/channels/chan_jingle.c
team/oej/codename-pineapple/channels/chan_local.c
team/oej/codename-pineapple/channels/chan_mgcp.c
team/oej/codename-pineapple/channels/chan_misdn.c
team/oej/codename-pineapple/channels/chan_nbs.c
team/oej/codename-pineapple/channels/chan_oss.c
team/oej/codename-pineapple/channels/chan_phone.c
team/oej/codename-pineapple/channels/chan_sip.c
team/oej/codename-pineapple/channels/chan_sip3.c
team/oej/codename-pineapple/channels/chan_skinny.c
team/oej/codename-pineapple/channels/chan_zap.c
team/oej/codename-pineapple/channels/sip3/Makefile
team/oej/codename-pineapple/channels/sip3/sip3_auth.c
team/oej/codename-pineapple/channels/sip3/sip3_callerid.c
team/oej/codename-pineapple/channels/sip3/sip3_cliami.c
team/oej/codename-pineapple/channels/sip3/sip3_compose.c
team/oej/codename-pineapple/channels/sip3/sip3_config.c
team/oej/codename-pineapple/channels/sip3/sip3_dialog.c
team/oej/codename-pineapple/channels/sip3/sip3_domain.c
team/oej/codename-pineapple/channels/sip3/sip3_network.c
team/oej/codename-pineapple/channels/sip3/sip3_parse.c
team/oej/codename-pineapple/channels/sip3/sip3_refer.c
team/oej/codename-pineapple/channels/sip3/sip3_sdprtp.c
team/oej/codename-pineapple/channels/sip3/sip3_services.c
team/oej/codename-pineapple/channels/sip3/sip3_subscribe.c
team/oej/codename-pineapple/channels/sip3/sip3funcs.h
team/oej/codename-pineapple/configure
team/oej/codename-pineapple/include/asterisk/channel.h
team/oej/codename-pineapple/include/asterisk/frame.h
team/oej/codename-pineapple/include/asterisk/manager.h
team/oej/codename-pineapple/include/asterisk/stringfields.h
team/oej/codename-pineapple/main/app.c
team/oej/codename-pineapple/main/asterisk.c
team/oej/codename-pineapple/main/channel.c
team/oej/codename-pineapple/main/cli.c
team/oej/codename-pineapple/main/frame.c
team/oej/codename-pineapple/main/logger.c
team/oej/codename-pineapple/main/manager.c
team/oej/codename-pineapple/main/pbx.c
team/oej/codename-pineapple/main/utils.c
team/oej/codename-pineapple/pbx/pbx_dundi.c
team/oej/codename-pineapple/res/res_agi.c
team/oej/codename-pineapple/res/res_features.c
team/oej/codename-pineapple/res/res_musiconhold.c
Modified: team/oej/codename-pineapple/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/apps/app_dial.c?view=diff&rev=47362&r1=47361&r2=47362
==============================================================================
--- team/oej/codename-pineapple/apps/app_dial.c (original)
+++ team/oej/codename-pineapple/apps/app_dial.c Thu Nov 9 07:44:09 2006
@@ -318,30 +318,47 @@
#define AST_MAX_WATCHERS 256
-#define HANDLE_CAUSE(cause, chan) do { \
- switch(cause) { \
- case AST_CAUSE_BUSY: \
- if (chan->cdr) \
- ast_cdr_busy(chan->cdr); \
- numbusy++; \
- break; \
- case AST_CAUSE_CONGESTION: \
- if (chan->cdr) \
- ast_cdr_failed(chan->cdr); \
- numcongestion++; \
- break; \
- case AST_CAUSE_UNREGISTERED: \
- if (chan->cdr) \
- ast_cdr_failed(chan->cdr); \
- numnochan++; \
- break; \
- case AST_CAUSE_NORMAL_CLEARING: \
- break; \
- default: \
- numnochan++; \
- break; \
- } \
-} while (0)
+/*
+ * argument to handle_cause() and other functions.
+ */
+struct cause_args {
+ struct ast_channel *chan;
+ int busy;
+ int congestion;
+ int nochan;
+};
+
+static void handle_cause(int cause, struct cause_args *num)
+{
+ struct ast_cdr *cdr = num->chan->cdr;
+
+ switch(cause) {
+ case AST_CAUSE_BUSY:
+ if (cdr)
+ ast_cdr_busy(cdr);
+ num->busy++;
+ break;
+
+ case AST_CAUSE_CONGESTION:
+ if (cdr)
+ ast_cdr_failed(cdr);
+ num->congestion++;
+ break;
+
+ case AST_CAUSE_UNREGISTERED:
+ if (cdr)
+ ast_cdr_failed(cdr);
+ num->nochan++;
+ break;
+
+ case AST_CAUSE_NORMAL_CLEARING:
+ break;
+
+ default:
+ num->nochan++;
+ break;
+ }
+}
/* free the buffer if allocated, and set the pointer to the second arg */
#define S_REPLACE(s, new_val) \
@@ -402,12 +419,113 @@
src->name, dialstatus);
}
-static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_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)
+/* helper function for wait_for_answer() */
+static void do_forward(struct dial_localuser *o,
+ struct cause_args *num, struct ast_flags *peerflags, int single)
{
- int numbusy = busystart;
- int numcongestion = congestionstart;
- int numnochan = nochanstart;
- int prestart = busystart + congestionstart + nochanstart;
+ char tmpchan[256];
+ struct ast_channel *c = o->chan; /* the winner */
+ struct ast_channel *in = num->chan; /* the input channel */
+ char *stuff;
+ char *tech;
+ int cause;
+
+ ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
+ if ((stuff = strchr(tmpchan, '/'))) {
+ *stuff++ = '\0';
+ tech = tmpchan;
+ } else {
+ const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
+ snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
+ stuff = tmpchan;
+ tech = "Local";
+ }
+ /* Before processing channel, go ahead and check for forwarding */
+ o->forwards++;
+ if (o->forwards < AST_MAX_FORWARDS) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
+ /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
+ if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
+ c = o->chan = NULL;
+ cause = AST_CAUSE_BUSY;
+ } else {
+ /* Setup parameters */
+ c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
+ if (!c)
+ ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
+ else
+ ast_channel_inherit_variables(in, o->chan);
+ }
+ } else {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", c->name);
+ cause = AST_CAUSE_CONGESTION;
+ c = o->chan = NULL;
+ }
+ if (!c) {
+ ast_clear_flag(o, DIAL_STILLGOING);
+ handle_cause(cause, num);
+ } else {
+ char *new_cid_num, *new_cid_name;
+ struct ast_channel *src;
+
+ ast_rtp_make_compatible(c, in, single);
+ if (ast_test_flag(o, OPT_FORCECLID)) {
+ new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
+ new_cid_name = NULL; /* XXX no name ? */
+ src = c; /* XXX possible bug in previous code, which used 'winner' ? it may have changed */
+ } else {
+ new_cid_num = ast_strdup(in->cid.cid_num);
+ new_cid_name = ast_strdup(in->cid.cid_name);
+ src = in;
+ }
+ ast_string_field_set(c, accountcode, src->accountcode);
+ c->cdrflags = src->cdrflags;
+ S_REPLACE(c->cid.cid_num, new_cid_num);
+ S_REPLACE(c->cid.cid_name, new_cid_name);
+
+ if (in->cid.cid_ani) { /* XXX or maybe unconditional ? */
+ S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
+ }
+ S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
+ if (ast_call(c, tmpchan, 0)) {
+ ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
+ ast_clear_flag(o, DIAL_STILLGOING);
+ ast_hangup(c);
+ c = o->chan = NULL;
+ num->nochan++;
+ } else {
+ senddialevent(in, c);
+ /* After calling, set callerid to extension */
+ if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) {
+ char cidname[AST_MAX_EXTENSION];
+ ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
+ }
+ }
+ }
+ /* Hangup the original channel now, in case we needed it */
+ ast_hangup(c);
+}
+
+/* argument used for some functions. */
+struct privacy_args {
+ int sentringing;
+ int privdb_val;
+ char privcid[256];
+ char privintro[1024];
+ char status[256];
+};
+
+static struct ast_channel *wait_for_answer(struct ast_channel *in,
+ struct dial_localuser *outgoing, int *to, struct ast_flags *peerflags,
+ struct privacy_args *pa,
+ const struct cause_args *num_in, int priority_jump, int *result)
+{
+ struct cause_args num = *num_in;
+ int prestart = num.busy + num.congestion + num.nochan;
int orig = *to;
struct ast_channel *peer = NULL;
/* single is set if only one destination is enabled */
@@ -436,20 +554,20 @@
numlines++;
}
if (pos == 1) { /* only the input channel is available */
- if (numlines == (numbusy + numcongestion + numnochan)) {
+ if (numlines == (num.busy + num.congestion + num.nochan)) {
if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
- if (numbusy)
- strcpy(status, "BUSY");
- else if (numcongestion)
- strcpy(status, "CONGESTION");
- else if (numnochan)
- strcpy(status, "CHANUNAVAIL");
+ ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
+ if (num.busy)
+ strcpy(pa->status, "BUSY");
+ else if (num.congestion)
+ strcpy(pa->status, "CONGESTION");
+ else if (num.nochan)
+ strcpy(pa->status, "CHANUNAVAIL");
if (ast_opt_priority_jumping || priority_jump)
ast_goto_if_exists(in, in->context, in->exten, in->priority + 101);
} else {
if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
+ ast_verbose(VERBOSE_PREFIX_3 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
}
*to = 0;
return NULL;
@@ -479,91 +597,9 @@
}
if (c != winner)
continue;
+ /* here, o->chan == c == winner */
if (!ast_strlen_zero(c->call_forward)) {
- char tmpchan[256];
- char *stuff;
- char *tech;
- int cause;
-
- ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
- if ((stuff = strchr(tmpchan, '/'))) {
- *stuff++ = '\0';
- tech = tmpchan;
- } else {
- const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
- snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
- stuff = tmpchan;
- tech = "Local";
- }
- /* Before processing channel, go ahead and check for forwarding */
- o->forwards++;
- if (o->forwards < AST_MAX_FORWARDS) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
- /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
- if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
- c = o->chan = NULL;
- cause = AST_CAUSE_BUSY;
- } else {
- /* Setup parameters */
- c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
- if (!c)
- ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
- else
- ast_channel_inherit_variables(in, o->chan);
- }
- } else {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", c->name);
- cause = AST_CAUSE_CONGESTION;
- c = o->chan = NULL;
- }
- if (!c) {
- ast_clear_flag(o, DIAL_STILLGOING);
- HANDLE_CAUSE(cause, in);
- } else {
- ast_rtp_make_compatible(c, in, single);
- if (c->cid.cid_num)
- free(c->cid.cid_num);
- c->cid.cid_num = NULL;
- if (c->cid.cid_name)
- free(c->cid.cid_name);
- c->cid.cid_name = NULL;
-
- if (ast_test_flag(o, OPT_FORCECLID)) {
- c->cid.cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
- ast_string_field_set(c, accountcode, winner->accountcode);
- c->cdrflags = winner->cdrflags;
- } else {
- c->cid.cid_num = ast_strdup(in->cid.cid_num);
- c->cid.cid_name = ast_strdup(in->cid.cid_name);
- ast_string_field_set(c, accountcode, in->accountcode);
- c->cdrflags = in->cdrflags;
- }
-
- if (in->cid.cid_ani) {
- S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
- }
- S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
- if (ast_call(c, tmpchan, 0)) {
- ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
- ast_clear_flag(o, DIAL_STILLGOING);
- ast_hangup(c);
- c = o->chan = NULL;
- numnochan++;
- } else {
- senddialevent(in, c);
- /* After calling, set callerid to extension */
- if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) {
- char cidname[AST_MAX_EXTENSION];
- ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
- }
- }
- }
- /* Hangup the original channel now, in case we needed it */
- ast_hangup(winner);
+ do_forward(o, &num, peerflags, single);
continue;
}
f = ast_read(winner);
@@ -572,7 +608,7 @@
ast_hangup(c);
c = o->chan = NULL;
ast_clear_flag(o, DIAL_STILLGOING);
- HANDLE_CAUSE(in->hangupcause, in);
+ handle_cause(in->hangupcause, &num);
continue;
}
if (f->frametype == AST_FRAME_CONTROL) {
@@ -605,7 +641,7 @@
ast_hangup(c);
c = o->chan = NULL;
ast_clear_flag(o, DIAL_STILLGOING);
- HANDLE_CAUSE(AST_CAUSE_BUSY, in);
+ handle_cause(AST_CAUSE_BUSY, &num);
break;
case AST_CONTROL_CONGESTION:
if (option_verbose > 2)
@@ -614,7 +650,7 @@
ast_hangup(c);
c = o->chan = NULL;
ast_clear_flag(o, DIAL_STILLGOING);
- HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
+ handle_cause(AST_CAUSE_CONGESTION, &num);
break;
case AST_CONTROL_RINGING:
if (option_verbose > 2)
@@ -622,9 +658,9 @@
/* Setup early media if appropriate */
if (single)
ast_channel_early_bridge(in, c);
- if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
+ if (!(pa->sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
ast_indicate(in, AST_CONTROL_RINGING);
- (*sentringing)++;
+ pa->sentringing++;
}
break;
case AST_CONTROL_PROGRESS:
@@ -668,7 +704,7 @@
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name);
ast_indicate(in, -1);
- (*sentringing) = 0;
+ pa->sentringing = 0;
}
break;
default:
@@ -704,13 +740,14 @@
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
/* Got hung up */
*to = -1;
- strcpy(status, "CANCEL");
+ strcpy(pa->status, "CANCEL");
if (f)
ast_frfree(f);
return NULL;
}
- if (f && (f->frametype == AST_FRAME_DTMF)) {
+ /* now f is guaranteed non-NULL */
+ if (f->frametype == AST_FRAME_DTMF) {
if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) {
const char *context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
if (onedigit_goto(in, context, (char) f->subclass, 1)) {
@@ -718,7 +755,7 @@
ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
*to=0;
*result = f->subclass;
- strcpy(status, "CANCEL");
+ strcpy(pa->status, "CANCEL");
ast_frfree(f);
return NULL;
}
@@ -729,14 +766,14 @@
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
*to=0;
- strcpy(status, "CANCEL");
+ strcpy(pa->status, "CANCEL");
ast_frfree(f);
return NULL;
}
}
/* Forward HTML stuff */
- if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML))
+ if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML))
if(ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen) == -1)
ast_log(LOG_WARNING, "Unable to send URL\n");
@@ -782,37 +819,259 @@
return 0;
}
+static int do_timelimit(struct ast_channel *chan, struct ast_bridge_config *config,
+ char *parse, unsigned int *calldurationlimit)
+{
+ char *limit_str, *warning_str, *warnfreq_str;
+ const char *var;
+ int play_to_caller=0,play_to_callee=0;
+ int delta;
+
+ limit_str = strsep(&warnfreq_str, ":");
+ warning_str = strsep(&warnfreq_str, ":");
+ warnfreq_str = parse;
+
+ config->timelimit = atol(limit_str);
+ if (warning_str)
+ config->play_warning = atol(warning_str);
+ if (warnfreq_str)
+ config->warning_freq = atol(warnfreq_str);
+
+ if (!config->timelimit) {
+ ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
+ config->timelimit = config->play_warning = config->warning_freq = 0;
+ config->warning_sound = NULL;
+ return -1; /* error */
+ } else if ( (delta = config->play_warning - config->timelimit) > 0) {
+ int w = config->warning_freq;
+
+ /* If the first warning is requested _after_ the entire call would end,
+ and no warning frequency is requested, then turn off the warning. If
+ a warning frequency is requested, reduce the 'first warning' time by
+ that frequency until it falls within the call's total time limit.
+ Graphically:
+ timelim->| delta |<-playwarning
+ 0__________________|_________________|
+ | w | | | |
+
+ so the number of intervals to cut is 1+(delta-1)/w
+ */
+
+ if (w == 0) {
+ config->play_warning = 0;
+ } else {
+ config->play_warning -= w * ( 1 + (delta-1)/w );
+ if (config->play_warning < 1)
+ config->play_warning = config->warning_freq = 0;
+ }
+ }
+
+ var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
+ play_to_caller = var ? ast_true(var) : 1;
+
+ var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
+ play_to_callee = var ? ast_true(var) : 0;
+
+ if (!play_to_caller && !play_to_callee)
+ play_to_caller = 1;
+
+ var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
+ config->warning_sound = S_OR(var, "timeleft");
+
+ /* The code looking at config wants a NULL, not just "", to decide
+ * that the message should not be played, so we replace "" with NULL.
+ * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
+ * not found.
+ */
+ var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
+ config->end_sound = S_OR(var, NULL);
+ var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
+ config->start_sound = S_OR(var, NULL);
+
+ /* undo effect of S(x) in case they are both used */
+ *calldurationlimit = 0;
+ /* more efficient to do it like S(x) does since no advanced opts */
+ if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
+ *calldurationlimit = config->timelimit / 1000;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n",
+ *calldurationlimit);
+ config->timelimit = play_to_caller = play_to_callee =
+ config->play_warning = config->warning_freq = 0;
+ } else if (option_verbose > 2) {
+ ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n");
+ ast_verbose(VERBOSE_PREFIX_4 "timelimit = %ld\n", config->timelimit);
+ ast_verbose(VERBOSE_PREFIX_4 "play_warning = %ld\n", config->play_warning);
+ ast_verbose(VERBOSE_PREFIX_4 "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
+ ast_verbose(VERBOSE_PREFIX_4 "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
+ ast_verbose(VERBOSE_PREFIX_4 "warning_freq = %ld\n", config->warning_freq);
+ ast_verbose(VERBOSE_PREFIX_4 "start_sound = %s\n", S_OR(config->start_sound, ""));
+ ast_verbose(VERBOSE_PREFIX_4 "warning_sound = %s\n", config->warning_sound);
+ ast_verbose(VERBOSE_PREFIX_4 "end_sound = %s\n", S_OR(config->end_sound, ""));
+ }
+ if (play_to_caller)
+ ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
+ if (play_to_callee)
+ ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
+ return 0;
+}
+
+static int do_privacy(struct ast_channel *chan, struct ast_channel *peer,
+ struct ast_flags *opts, char **opt_args, struct privacy_args *pa)
+{
+
+ int res2;
+ int loopcount = 0;
+
+ /* 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 */
+
+ 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], NULL);
+ } else if (ast_test_flag(opts, OPT_RINGBACK)) {
+ ast_indicate(chan, AST_CONTROL_RINGING);
+ pa->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, pa->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);
+ pa->sentringing=0;
+ }
+ ast_autoservice_stop(chan);
+ if(ast_test_flag(opts, OPT_PRIVACY) && (res2 >= '1' && res2 <= '5')) {
+ /* map keypresses to various things, the index is res2 - '1' */
+ static const char *_val[] = { "ALLOW", "DENY", "TORTURE", "KILL", "ALLOW" };
+ static const int _flag[] = { AST_PRIVACY_ALLOW, AST_PRIVACY_DENY, AST_PRIVACY_TORTURE, AST_PRIVACY_KILL, AST_PRIVACY_ALLOW};
+ int i = res2 - '1';
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to %s\n",
+ opt_args[OPT_ARG_PRIVACY], pa->privcid, _val[i]);
+ ast_privacy_set(opt_args[OPT_ARG_PRIVACY], pa->privcid, _flag[i]);
+ }
+ switch (res2) {
+ case '1':
+ break;
+ case '2':
+ ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
+ break;
+ case '3':
+ ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
+ break;
+ case '4':
+ ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
+ break;
+ case '5':
+ /* XXX should we set status to DENY ? */
+ if( ast_test_flag(opts, OPT_PRIVACY) )
+ break;
+ /* 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");
+ /* XXX should we set status to DENY ? */
+ /* XXX what about the privacy flags ? */
+ break;
+ }
+
+ if (res2 == '1') { /* the only case where we actually connect */
+ /* 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(pa->privcid,"NOCALLERID",10) == 0 || ast_test_flag(opts, OPT_SCREEN_NOINTRO) ) {
+ ast_filedelete(pa->privintro, NULL);
+ if( ast_fileexists(pa->privintro, NULL, NULL ) > 0 )
+ ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
+ else if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", pa->privintro);
+ }
+ return 0; /* the good exit path */
+ } else {
+ ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
+ return -1;
+ }
+}
+
static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags)
{
- int res = -1;
+ int res = -1; /* default: error */
struct ast_module_user *u;
- char *rest, *cur;
- struct dial_localuser *outgoing = NULL;
+ char *rest, *cur; /* scan the list of destinations */
+ struct dial_localuser *outgoing = NULL; /* list of destinations */
struct ast_channel *peer;
- int to;
- int numbusy = 0;
- int numcongestion = 0;
- int numnochan = 0;
+ int to; /* timeout */
+ struct cause_args num = { chan, 0, 0, 0 };
int cause;
char numsubst[AST_MAX_EXTENSION];
char cidname[AST_MAX_EXTENSION];
- int privdb_val = 0;
+
+ struct ast_bridge_config config;
unsigned int calldurationlimit = 0;
- long timelimit = 0;
- long play_warning = 0;
- long warning_freq = 0;
- const char *warning_sound = NULL;
- const char *end_sound = NULL;
- const char *start_sound = NULL;
char *dtmfcalled = NULL, *dtmfcalling = NULL;
- char status[256];
- int play_to_caller = 0, play_to_callee = 0;
+ struct privacy_args pa = {
+ .sentringing = 0,
+ .privdb_val = 0,
+ };
int sentringing = 0, moh = 0;
const char *outbound_group = NULL;
int result = 0;
time_t start_time;
- char privintro[1024];
- char privcid[256];
char *parse;
int opermode = 0;
AST_DECLARE_APP_ARGS(args,
@@ -829,11 +1088,13 @@
return -1;
}
- u = ast_module_user_add(chan);
+ u = ast_module_user_add(chan); /* XXX is this the right place ? */
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
+
+ memset(&config,0,sizeof(struct ast_bridge_config));
if (!ast_strlen_zero(args.options) &&
ast_app_parse_options(dial_exec_options, &opts, opt_args, args.options))
@@ -845,9 +1106,7 @@
}
if (ast_test_flag(&opts, OPT_OPERMODE)) {
- if (ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]))
- opermode = 1;
- else opermode = atoi(opt_args[OPT_ARG_OPERMODE]);
+ opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Setting operator services mode to %d.\n", opermode);
}
@@ -868,77 +1127,8 @@
}
if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
- char *limit_str, *warning_str, *warnfreq_str;
- const char *var;
-
- warnfreq_str = opt_args[OPT_ARG_DURATION_LIMIT];
- limit_str = strsep(&warnfreq_str, ":");
- warning_str = strsep(&warnfreq_str, ":");
-
- timelimit = atol(limit_str);
- if (warning_str)
- play_warning = atol(warning_str);
- if (warnfreq_str)
- warning_freq = atol(warnfreq_str);
-
- if (!timelimit) {
- ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
+ if (do_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
goto done;
- } else if (play_warning > timelimit) {
- /* If the first warning is requested _after_ the entire call would end,
- and no warning frequency is requested, then turn off the warning. If
- a warning frequency is requested, reduce the 'first warning' time by
- that frequency until it falls within the call's total time limit.
- */
-
- if (!warning_freq) {
- play_warning = 0;
- } else {
- /* XXX fix this!! */
- while (play_warning > timelimit)
- play_warning -= warning_freq;
- if (play_warning < 1)
- play_warning = warning_freq = 0;
- }
- }
-
- var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
- play_to_caller = var ? ast_true(var) : 1;
-
- var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
- play_to_callee = var ? ast_true(var) : 0;
-
- if (!play_to_caller && !play_to_callee)
- play_to_caller = 1;
-
- var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
- warning_sound = S_OR(var, "timeleft");
-
- var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
- end_sound = S_OR(var, NULL); /* XXX not much of a point in doing this! */
-
- var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
- start_sound = S_OR(var, NULL); /* XXX not much of a point in doing this! */
-
- /* undo effect of S(x) in case they are both used */
- calldurationlimit = 0;
- /* more efficient to do it like S(x) does since no advanced opts */
- if (!play_warning && !start_sound && !end_sound && timelimit) {
- calldurationlimit = timelimit / 1000;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
- timelimit = play_to_caller = play_to_callee = play_warning = warning_freq = 0;
- } else if (option_verbose > 2) {
- ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n");
- ast_verbose(VERBOSE_PREFIX_4 "timelimit = %ld\n", timelimit);
- ast_verbose(VERBOSE_PREFIX_4 "play_warning = %ld\n", play_warning);
- ast_verbose(VERBOSE_PREFIX_4 "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
- ast_verbose(VERBOSE_PREFIX_4 "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
- ast_verbose(VERBOSE_PREFIX_4 "warning_freq = %ld\n", warning_freq);
- ast_verbose(VERBOSE_PREFIX_4 "start_sound = %s\n", start_sound);
- ast_verbose(VERBOSE_PREFIX_4 "warning_sound = %s\n", warning_sound);
- ast_verbose(VERBOSE_PREFIX_4 "end_sound = %s\n", end_sound);
- }
}
if (ast_test_flag(&opts, OPT_RESETCDR) && chan->cdr)
@@ -954,12 +1144,12 @@
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Privacy DB is '%s', clid is '%s'\n",
opt_args[OPT_ARG_PRIVACY], l);
- privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
+ pa.privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
}
else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Privacy Screening, clid is '%s'\n", l);
- privdb_val = AST_PRIVACY_UNKNOWN;
+ pa.privdb_val = AST_PRIVACY_UNKNOWN;
}
} else {
char *tnam, *tn2;
@@ -975,59 +1165,59 @@
snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
l = callerid;
- privdb_val = AST_PRIVACY_UNKNOWN;
+ pa.privdb_val = AST_PRIVACY_UNKNOWN;
}
- ast_copy_string(privcid,l,sizeof(privcid));
-
- if( strncmp(privcid,"NOCALLERID",10) != 0 && ast_test_flag(&opts, OPT_SCREEN_NOCLID) ) { /* if callerid is set, and ast_test_flag(&opts, OPT_SCREEN_NOCLID) is set also */
+ ast_copy_string(pa.privcid,l,sizeof(pa.privcid));
+
+ if( strncmp(pa.privcid,"NOCALLERID",10) != 0 && ast_test_flag(&opts, OPT_SCREEN_NOCLID) ) { /* if callerid is set, and ast_test_flag(&opts, OPT_SCREEN_NOCLID) is set also */
if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "CallerID set (%s); N option set; Screening should be off\n", privcid);
- privdb_val = AST_PRIVACY_ALLOW;
- }
- else if(ast_test_flag(&opts, OPT_SCREEN_NOCLID) && strncmp(privcid,"NOCALLERID",10) == 0 ) {
+ ast_verbose( VERBOSE_PREFIX_3 "CallerID set (%s); N option set; Screening should be off\n", pa.privcid);
+ pa.privdb_val = AST_PRIVACY_ALLOW;
+ }
+ else if(ast_test_flag(&opts, OPT_SCREEN_NOCLID) && strncmp(pa.privcid,"NOCALLERID",10) == 0 ) {
if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val);
+ ast_verbose( VERBOSE_PREFIX_3 "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa.privdb_val);
}
- if(privdb_val == AST_PRIVACY_DENY ) {
- ast_copy_string(status, "NOANSWER", sizeof(status));
+ if(pa.privdb_val == AST_PRIVACY_DENY ) {
+ ast_copy_string(pa.status, "NOANSWER", sizeof(pa.status));
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
res=0;
goto out;
}
- else if(privdb_val == AST_PRIVACY_KILL ) {
- ast_copy_string(status, "DONTCALL", sizeof(status));
+ else if(pa.privdb_val == AST_PRIVACY_KILL ) {
+ ast_copy_string(pa.status, "DONTCALL", sizeof(pa.status));
if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
}
res = 0;
goto out; /* Is this right? */
}
- else if(privdb_val == AST_PRIVACY_TORTURE ) {
- ast_copy_string(status, "TORTURE", sizeof(status));
+ else if(pa.privdb_val == AST_PRIVACY_TORTURE ) {
+ ast_copy_string(pa.status, "TORTURE", sizeof(pa.status));
if (ast_opt_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
}
res = 0;
goto out; /* is this right??? */
}
- else if(privdb_val == AST_PRIVACY_UNKNOWN ) {
+ else if(pa.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 */
/* make sure the priv-callerintros dir actually exists */
- snprintf(privintro, sizeof(privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
- if (mkdir(privintro, 0755) && errno != EEXIST) {
+ snprintf(pa.privintro, sizeof(pa.privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
+ if (mkdir(pa.privintro, 0755) && errno != EEXIST) {
ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(errno));
res = -1;
goto out;
}
- snprintf(privintro,sizeof(privintro), "priv-callerintros/%s", privcid);
- if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) {
+ snprintf(pa.privintro,sizeof(pa.privintro), "priv-callerintros/%s", pa.privcid);
+ if( ast_fileexists(pa.privintro,NULL,NULL ) > 0 && strncmp(pa.privcid,"NOCALLERID",10) != 0) {
/* the DELUX version of this code would allow this caller the
option to hear and retape their previously recorded intro.
*/
@@ -1041,16 +1231,16 @@
"At the tone, please say your name:"
*/
- res = ast_play_and_record(chan, "priv-recordintro", privintro, 4, "gsm", &duration, 128, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */
+ res = ast_play_and_record(chan, "priv-recordintro", pa.privintro, 4, "gsm", &duration, 128, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */
/* don't think we'll need a lock removed, we took care of
- conflicts by naming the privintro file */
+ conflicts by naming the pa.privintro file */
if (res == -1) {
/* Delete the file regardless since they hung up during recording */
- 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);
+ ast_filedelete(pa.privintro, NULL);
+ if( ast_fileexists(pa.privintro,NULL,NULL ) > 0 )
+ ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", pa.privintro);
else if (option_verbose > 2)
- ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro);
+ ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", pa.privintro);
goto out;
}
if( !ast_streamfile(chan, "vm-dialout", chan->language) )
@@ -1091,7 +1281,7 @@
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));
- HANDLE_CAUSE(cause, chan);
+ handle_cause(cause, &num);
if (!rest) /* we are on the last destination */
chan->hangupcause = cause;
continue;
@@ -1136,7 +1326,7 @@
cause = AST_CAUSE_CONGESTION;
}
if (!tmp->chan) {
- HANDLE_CAUSE(cause, chan);
+ handle_cause(cause, &num);
continue;
}
}
@@ -1227,10 +1417,10 @@
}
if (!outgoing) {
- strcpy(status, "CHANUNAVAIL");
+ strcpy(pa.status, "CHANUNAVAIL");
} else {
/* Our status will at least be NOANSWER */
- strcpy(status, "NOANSWER");
+ strcpy(pa.status, "NOANSWER");
if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
moh = 1;
ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
@@ -1241,7 +1431,7 @@
}
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);
+ peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
if (!peer) {
if (result) {
@@ -1255,8 +1445,9 @@
} else {
const char *number;
time_t end_time, answer_time = time(NULL);
-
[... 9621 lines stripped ...]
More information about the asterisk-commits
mailing list