[asterisk-commits] murf: branch murf/fast-ast r47479 - in
/team/murf/fast-ast: ./ apps/ channels...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Fri Nov 10 15:20:03 MST 2006
Author: murf
Date: Fri Nov 10 16:20:02 2006
New Revision: 47479
URL: http://svn.digium.com/view/asterisk?view=rev&rev=47479
Log:
merged in changed from automerge; tossed the description. Implemented rwlocks in hashtab and stringtab. Added some comments. Stringtab slows down the engine a bit-- for now. Not done yet.
Removed:
team/murf/fast-ast/aclocal.m4
Modified:
team/murf/fast-ast/ (props changed)
team/murf/fast-ast/CHANGES
team/murf/fast-ast/UPGRADE.txt
team/murf/fast-ast/acinclude.m4
team/murf/fast-ast/apps/app_dial.c
team/murf/fast-ast/apps/app_queue.c
team/murf/fast-ast/apps/app_voicemail.c
team/murf/fast-ast/channels/chan_agent.c
team/murf/fast-ast/channels/chan_alsa.c
team/murf/fast-ast/channels/chan_features.c
team/murf/fast-ast/channels/chan_gtalk.c
team/murf/fast-ast/channels/chan_h323.c
team/murf/fast-ast/channels/chan_iax2.c
team/murf/fast-ast/channels/chan_jingle.c
team/murf/fast-ast/channels/chan_local.c
team/murf/fast-ast/channels/chan_mgcp.c
team/murf/fast-ast/channels/chan_misdn.c
team/murf/fast-ast/channels/chan_nbs.c
team/murf/fast-ast/channels/chan_oss.c
team/murf/fast-ast/channels/chan_phone.c
team/murf/fast-ast/channels/chan_sip.c
team/murf/fast-ast/channels/chan_skinny.c
team/murf/fast-ast/channels/chan_vpb.cc
team/murf/fast-ast/channels/chan_zap.c
team/murf/fast-ast/configs/manager.conf.sample
team/murf/fast-ast/configs/musiconhold.conf.sample
team/murf/fast-ast/configs/sip.conf.sample
team/murf/fast-ast/configs/zapata.conf.sample
team/murf/fast-ast/configure
team/murf/fast-ast/configure.ac
team/murf/fast-ast/include/asterisk/channel.h
team/murf/fast-ast/include/asterisk/frame.h
team/murf/fast-ast/include/asterisk/manager.h
team/murf/fast-ast/include/asterisk/stringfields.h
team/murf/fast-ast/main/app.c
team/murf/fast-ast/main/asterisk.c
team/murf/fast-ast/main/channel.c
team/murf/fast-ast/main/cli.c
team/murf/fast-ast/main/frame.c
team/murf/fast-ast/main/hashtab.c
team/murf/fast-ast/main/hashtab.h
team/murf/fast-ast/main/logger.c
team/murf/fast-ast/main/manager.c
team/murf/fast-ast/main/pbx.c
team/murf/fast-ast/main/stringtab.c
team/murf/fast-ast/main/stringtab.h
team/murf/fast-ast/main/utils.c
team/murf/fast-ast/pbx/pbx_dundi.c
team/murf/fast-ast/res/res_agi.c
team/murf/fast-ast/res/res_features.c
team/murf/fast-ast/res/res_musiconhold.c
team/murf/fast-ast/utils/astman.c
team/murf/fast-ast/utils/check_expr.c
team/murf/fast-ast/utils/streamplayer.c
Propchange: team/murf/fast-ast/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.
Propchange: team/murf/fast-ast/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.
Propchange: team/murf/fast-ast/
------------------------------------------------------------------------------
--- svn:externals (original)
+++ svn:externals Fri Nov 10 16:20:02 2006
@@ -1,1 +1,1 @@
-menuselect http://svn.digium.com/svn/menuselect/branches/1.0
+menuselect https://origsvn.digium.com/svn/menuselect/branches/1.0
Propchange: team/murf/fast-ast/
('svnmerge-blocked' removed)
Propchange: team/murf/fast-ast/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri Nov 10 16:20:02 2006
@@ -1,1 +1,1 @@
-/trunk:1-47165
+/trunk:1-47361
Modified: team/murf/fast-ast/CHANGES
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/CHANGES?view=diff&rev=47479&r1=47478&r2=47479
==============================================================================
--- team/murf/fast-ast/CHANGES (original)
+++ team/murf/fast-ast/CHANGES Fri Nov 10 16:20:02 2006
@@ -58,3 +58,4 @@
* Added QUEUE_VARIABLES function to set queue variables added setqueuevar and
setqueueentryvar options for each queue, see queues.conf.sample for details.
* Brazilian Portuguese (pt-BR) in VM, and say.c was added via patch from cfassoni.
+ * CID matching information is now shown when doing 'dialplan show'.
Modified: team/murf/fast-ast/UPGRADE.txt
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/UPGRADE.txt?view=diff&rev=47479&r1=47478&r2=47479
==============================================================================
--- team/murf/fast-ast/UPGRADE.txt (original)
+++ team/murf/fast-ast/UPGRADE.txt Fri Nov 10 16:20:02 2006
@@ -3,6 +3,6 @@
Manager:
-* The CallerID fields across manager events have now been made more
+* The CallerID fields across Manager events have now been made more
consistent. CallerID Number will be sent as CallerIDNum and CallerID
Name will be sent as CallerIDName wherever used.
Modified: team/murf/fast-ast/acinclude.m4
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/acinclude.m4?view=diff&rev=47479&r1=47478&r2=47479
==============================================================================
--- team/murf/fast-ast/acinclude.m4 (original)
+++ team/murf/fast-ast/acinclude.m4 Fri Nov 10 16:20:02 2006
@@ -567,3 +567,119 @@
[ac_cv_func_fork_works=no],
[ac_cv_func_fork_works=cross])])]
)# _AST_FUNC_FORK
+
+# AST_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AST_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+ [AC_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])
+AC_REQUIRE([AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AST_PROG_LD_GNU
+])# AST_PROG_LD
+
+
+# AST_PROG_LD_GNU
+# --------------
+AC_DEFUN([AST_PROG_LD_GNU],
+[AC_REQUIRE([AST_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AST_PROG_LD_GNU
+
+# AST_PROG_EGREP
+# -------------
+m4_ifndef([AST_PROG_EGREP], [AC_DEFUN([AST_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+ [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])]) # AST_PROG_EGREP
+
+
Modified: team/murf/fast-ast/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/apps/app_dial.c?view=diff&rev=47479&r1=47478&r2=47479
==============================================================================
--- team/murf/fast-ast/apps/app_dial.c (original)
+++ team/murf/fast-ast/apps/app_dial.c Fri Nov 10 16:20:02 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 ) {
[... 9810 lines stripped ...]
More information about the asterisk-commits
mailing list