[svn-commits] tilghman: branch tilghman/str_substitution r191095 - in /team/tilghman/str_su...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Apr 29 12:31:32 CDT 2009


Author: tilghman
Date: Wed Apr 29 12:31:24 2009
New Revision: 191095

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=191095
Log:
resolve conflicts

Added:
    team/tilghman/str_substitution/include/asterisk/autochan.h
      - copied unchanged from r191028, trunk/include/asterisk/autochan.h
    team/tilghman/str_substitution/main/autochan.c
      - copied unchanged from r191028, trunk/main/autochan.c
Removed:
    team/tilghman/str_substitution/apps/app_dahdiscan.c
Modified:
    team/tilghman/str_substitution/   (props changed)
    team/tilghman/str_substitution/CHANGES
    team/tilghman/str_substitution/Makefile
    team/tilghman/str_substitution/Makefile.rules
    team/tilghman/str_substitution/UPGRADE.txt
    team/tilghman/str_substitution/apps/app_channelredirect.c
    team/tilghman/str_substitution/apps/app_chanspy.c
    team/tilghman/str_substitution/apps/app_directed_pickup.c
    team/tilghman/str_substitution/apps/app_minivm.c
    team/tilghman/str_substitution/apps/app_mixmonitor.c
    team/tilghman/str_substitution/apps/app_osplookup.c
    team/tilghman/str_substitution/apps/app_queue.c
    team/tilghman/str_substitution/apps/app_senddtmf.c
    team/tilghman/str_substitution/apps/app_softhangup.c
    team/tilghman/str_substitution/apps/app_voicemail.c
    team/tilghman/str_substitution/build_tools/cflags.xml
    team/tilghman/str_substitution/channels/chan_agent.c
    team/tilghman/str_substitution/channels/chan_bridge.c
    team/tilghman/str_substitution/channels/chan_dahdi.c
    team/tilghman/str_substitution/channels/chan_gtalk.c
    team/tilghman/str_substitution/channels/chan_iax2.c
    team/tilghman/str_substitution/channels/chan_local.c
    team/tilghman/str_substitution/channels/chan_mgcp.c
    team/tilghman/str_substitution/channels/chan_misdn.c
    team/tilghman/str_substitution/channels/chan_sip.c
    team/tilghman/str_substitution/channels/chan_unistim.c
    team/tilghman/str_substitution/channels/misdn/isdn_lib.c
    team/tilghman/str_substitution/channels/misdn/isdn_lib.h
    team/tilghman/str_substitution/configs/http.conf.sample
    team/tilghman/str_substitution/configs/manager.conf.sample
    team/tilghman/str_substitution/configs/sip.conf.sample
    team/tilghman/str_substitution/configure
    team/tilghman/str_substitution/doc/tex/cdrdriver.tex
    team/tilghman/str_substitution/doc/tex/channelvariables.tex
    team/tilghman/str_substitution/funcs/func_channel.c
    team/tilghman/str_substitution/funcs/func_connectedline.c
    team/tilghman/str_substitution/funcs/func_global.c
    team/tilghman/str_substitution/funcs/func_logic.c
    team/tilghman/str_substitution/funcs/func_odbc.c
    team/tilghman/str_substitution/funcs/func_redirecting.c
    team/tilghman/str_substitution/include/asterisk/channel.h
    team/tilghman/str_substitution/include/asterisk/lock.h
    team/tilghman/str_substitution/include/asterisk/tcptls.h
    team/tilghman/str_substitution/main/Makefile
    team/tilghman/str_substitution/main/channel.c
    team/tilghman/str_substitution/main/cli.c
    team/tilghman/str_substitution/main/devicestate.c
    team/tilghman/str_substitution/main/features.c
    team/tilghman/str_substitution/main/http.c
    team/tilghman/str_substitution/main/indications.c
    team/tilghman/str_substitution/main/logger.c
    team/tilghman/str_substitution/main/manager.c
    team/tilghman/str_substitution/main/pbx.c
    team/tilghman/str_substitution/main/rtp_engine.c
    team/tilghman/str_substitution/main/tcptls.c
    team/tilghman/str_substitution/res/res_agi.c
    team/tilghman/str_substitution/res/res_clioriginate.c
    team/tilghman/str_substitution/res/res_monitor.c
    team/tilghman/str_substitution/res/res_smdi.c
    team/tilghman/str_substitution/res/snmp/agent.c

Propchange: team/tilghman/str_substitution/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/tilghman/str_substitution/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.

Propchange: team/tilghman/str_substitution/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/tilghman/str_substitution/
            ('svnmerge' removed)

Propchange: team/tilghman/str_substitution/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Apr 29 12:31:24 2009
@@ -1,1 +1,1 @@
-/trunk:1-190418
+trunk:1-191028

Modified: team/tilghman/str_substitution/CHANGES
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/CHANGES?view=diff&rev=191095&r1=191094&r2=191095
==============================================================================
--- team/tilghman/str_substitution/CHANGES (original)
+++ team/tilghman/str_substitution/CHANGES Wed Apr 29 12:31:24 2009
@@ -20,6 +20,9 @@
  * Added SIP_CODEC_OUTBOUND dialplan variable which can be used to set the codec
    to be used for the outgoing call. It must be one of the codecs configured
    for the device.
+ * Added tlsprivatekey option to sip.conf.  This allows a separate .pem file
+   to be used for holding a private key.  If tlsprivatekey is not specified,
+   tlscertfile is searched for both public and private key.
 
 Applications
 ------------
@@ -28,6 +31,10 @@
    regardless if the call has been answered or not.
  * Added functionality to the app_dial F() option to continue with execution
    at the current location when no parameters are provided.
+ * Added c() option to app_chanspy. This option allows custom DTMF to be set
+   to cycle through the next avaliable channel.  By default this is still '*'.
+ * Added x() option to app_chanspy.  This option allows DTMF to be set to
+   exit the application.
 
 Dialplan Functions
 ------------------
@@ -65,6 +72,11 @@
     the CCBS/CCNR functionality.
   * Added new dialplan function mISDN_CC which permits retrieval of various
     values from an active call completion record.
+  * For PTP, you should manually send the COLR for an incomming redirected
+    call if the incoming call could or does experience further redirects.
+    Just set the REDIRECTING(to-num,i) = ${EXTEN} and set the
+    REDIRECTING(to-pres) to the COLR.  A call has been redirected if the
+    REDIRECTING(from-num) is not empty.
 
 thirdparty mISDN enhancements
 -----------------------------
@@ -92,7 +104,15 @@
 --------------------------
  * The Hangup action now accepts a Cause header which may be used to
    set the channel's hangup cause.
-
+ * sslprivatekey option added to manager.conf and http.conf.  Adds the ability
+   to specify a separate .pem file to hold a private key.  By default sslcert
+   is used to hold both the public and private key.
+ * Options in manager.conf and http.conf with the 'ssl' prefix have been replaced
+   for options containing the 'tls' prefix.  For example, 'sslenable' is now
+   'tlsenable'.  This has been done in effort to keep ssl and tls options consistent
+   across all .conf files. All affected sample.conf files have been modified to
+   reflect this change.  Previous options such as 'sslenable' still work,
+   but options with the 'tls' prefix are preferred.
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 1.6.1 to Asterisk 1.6.2  -------------
 ------------------------------------------------------------------------------

Modified: team/tilghman/str_substitution/Makefile
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/Makefile?view=diff&rev=191095&r1=191094&r2=191095
==============================================================================
--- team/tilghman/str_substitution/Makefile (original)
+++ team/tilghman/str_substitution/Makefile Wed Apr 29 12:31:24 2009
@@ -493,7 +493,7 @@
 	mkdir -p $(DESTDIR)$(AGI_DIR)
 	$(MAKE) -C sounds install
 
-doc/core-en_US.xml: $(foreach dir,$(MOD_SUBDIRS),$(wildcard $(dir)/*.c) $(wildcard $(dir)/*.cc)) 
+doc/core-en_US.xml: $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
 	@echo -n "Building Documentation For: "
 	@echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $@
 	@echo "<!DOCTYPE docs SYSTEM \"appdocsxml.dtd\">" >> $@

Modified: team/tilghman/str_substitution/Makefile.rules
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/Makefile.rules?view=diff&rev=191095&r1=191094&r2=191095
==============================================================================
--- team/tilghman/str_substitution/Makefile.rules (original)
+++ team/tilghman/str_substitution/Makefile.rules Wed Apr 29 12:31:24 2009
@@ -111,14 +111,6 @@
 	$(ECHO_PREFIX) echo "   [CPP] $< -> $@"
 	$(CMD_PREFIX) $(CXX) -o $@ -E $< $(CXX_CFLAGS) $(MAKE_DEPS)
 
-%.c: %.y
-	$(ECHO_PREFIX) echo "   [BISON] $< -> $@"
-	$(CMD_PREFIX) bison -o $@ -d --name-prefix=ast_yy $<
-
-%.c: %.fl
-	$(ECHO_PREFIX) echo "   [FLEX] $< -> $@"
-	$(CMD_PREFIX) flex -o $@ --full $<
-
 %.so: %.o
 	$(ECHO_PREFIX) echo "   [LD] $^ -> $@"
 	$(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(CC_LDFLAGS_SO) $^ $(CC_LIBS)

Modified: team/tilghman/str_substitution/UPGRADE.txt
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/UPGRADE.txt?view=diff&rev=191095&r1=191094&r2=191095
==============================================================================
--- team/tilghman/str_substitution/UPGRADE.txt (original)
+++ team/tilghman/str_substitution/UPGRADE.txt Wed Apr 29 12:31:24 2009
@@ -25,6 +25,9 @@
   If you are not using autoload=yes in modules.conf you will need to ensure
   it is set to load. If not, then any module which uses RTP (such as chan_sip)
   will not be able to send or receive calls.
+* The app_dahdiscan.c file has been removed, but the dialplan app DAHDIScan still 
+  remains. It now exists within app_chanspy.c and retains the exact same 
+  functionality as before. 
 
 From 1.6.1 to 1.6.2:
 

Modified: team/tilghman/str_substitution/apps/app_channelredirect.c
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/apps/app_channelredirect.c?view=diff&rev=191095&r1=191094&r2=191095
==============================================================================
--- team/tilghman/str_substitution/apps/app_channelredirect.c (original)
+++ team/tilghman/str_substitution/apps/app_channelredirect.c Wed Apr 29 12:31:24 2009
@@ -86,8 +86,7 @@
 		return -1;
 	}
 
-	chan2 = ast_get_channel_by_name_locked(args.channel);
-	if (!chan2) {
+	if (!(chan2 = ast_channel_get_by_name(args.channel))) {
 		ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
 		pbx_builtin_setvar_helper(chan, "CHANNELREDIRECT_STATUS", "NOCHANNEL");
 		return 0;
@@ -96,9 +95,12 @@
 	if (chan2->pbx) {
 		ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
 	}
+
 	res = ast_async_parseable_goto(chan2, args.label);
+
+	chan2 = ast_channel_unref(chan2);
+
 	pbx_builtin_setvar_helper(chan, "CHANNELREDIRECT_STATUS", "SUCCESS");
-	ast_channel_unlock(chan2);
 
 	return res;
 }

Modified: team/tilghman/str_substitution/apps/app_chanspy.c
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/apps/app_chanspy.c?view=diff&rev=191095&r1=191094&r2=191095
==============================================================================
--- team/tilghman/str_substitution/apps/app_chanspy.c (original)
+++ team/tilghman/str_substitution/apps/app_chanspy.c Wed Apr 29 12:31:24 2009
@@ -50,6 +50,7 @@
 #include "asterisk/module.h"
 #include "asterisk/lock.h"
 #include "asterisk/options.h"
+#include "asterisk/autochan.h"
 
 #define AST_NAME_STRLEN 256
 #define NUM_SPYGROUPS 128
@@ -140,6 +141,16 @@
 						specified by the <variable>SPY_EXIT_CONTEXT</variable> channel variable. The
 						name of the last channel that was spied on will be stored
 						in the <variable>SPY_CHANNEL</variable> variable.</para>
+					</option>
+					<option name="x">
+						<argument name="digit" required="true">
+							<para>Specify a DTMF digit that can be used to exit the application.</para>
+						</argument>
+					</option>
+					<option name="c">
+						<argument name="digit" required="true">
+							<para>Specify a DTMF digit that can be used to spy on the next available channel.</para>
+						</argument>
 					</option>
 					<option name="e">
 						<argument name="ext" required="true" />
@@ -262,6 +273,16 @@
 						name of the last channel that was spied on will be stored
 						in the <variable>SPY_CHANNEL</variable> variable.</para>
 					</option>
+					<option name="x">
+						<argument name="digit" required="true">
+							<para>Specify a DTMF digit that can be used to exit the application.</para>
+						</argument>
+					</option>
+					<option name="c">
+						<argument name="digit" required="true">
+							<para>Specify a DTMF digit that can be used to spy on the next available channel.</para>
+						</argument>
+					</option>
 					<option name="e">
 						<argument name="ext" required="true" />
 						<para>Enable <emphasis>enforced</emphasis> mode, so the spying channel can
@@ -287,11 +308,28 @@
 			<ref type="application">ChanSpy</ref>
 		</see-also>
 	</application>
-
+	
+	<application name="DAHDIScan" language="en_US">
+		<synopsis>
+			Scan DAHDI channels to monitor calls.
+		</synopsis>
+		<syntax>
+			<parameter name="group">
+				<para>Limit scanning to a channel <replaceable>group</replaceable> by setting this option.</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Allows a call center manager to monitor DAHDI channels in a
+			convenient way.  Use <literal>#</literal> to select the next channel and use <literal>*</literal> to exit.</para>
+		</description>
+	</application>
  ***/
+
 static const char *app_chan = "ChanSpy";
 
 static const char *app_ext = "ExtenSpy";
+
+static const char *app_dahdiscan = "DAHDIScan";
 
 enum {
 	OPTION_QUIET             = (1 << 0),    /* Quiet, no announcement */
@@ -307,7 +345,10 @@
 	OPTION_NOTECH            = (1 << 10),   /* Skip technology name playback */
 	OPTION_BARGE             = (1 << 11),   /* Barge mode (whisper to both channels) */
 	OPTION_NAME              = (1 << 12),   /* Say the name of the person on whom we will spy */
-	OPTION_DTMF_SWITCH_MODES = (1 << 13),   /*Allow numeric DTMF to switch between chanspy modes */
+	OPTION_DTMF_SWITCH_MODES = (1 << 13),   /* Allow numeric DTMF to switch between chanspy modes */
+	OPTION_DTMF_EXIT         = (1 << 14),	/* Set DTMF to exit, added for DAHDIScan integration */
+	OPTION_DTMF_CYCLE        = (1 << 15),	/* Custom DTMF for cycling next avaliable channel, (default is '*') */
+	OPTION_DAHDI_SCAN        = (1 << 16),	/* Scan groups in DAHDIScan mode */
 } chanspy_opt_flags;
 
 enum {
@@ -316,6 +357,8 @@
 	OPT_ARG_RECORD,
 	OPT_ARG_ENFORCED,
 	OPT_ARG_NAME,
+	OPT_ARG_EXIT,
+	OPT_ARG_CYCLE,
 	OPT_ARG_ARRAY_SIZE,
 } chanspy_opt_args;
 
@@ -334,9 +377,9 @@
 	AST_APP_OPTION('s', OPTION_NOTECH),
 	AST_APP_OPTION_ARG('n', OPTION_NAME, OPT_ARG_NAME),
 	AST_APP_OPTION('d', OPTION_DTMF_SWITCH_MODES),
+	AST_APP_OPTION_ARG('x', OPTION_DTMF_EXIT, OPT_ARG_EXIT),
+	AST_APP_OPTION_ARG('c', OPTION_DTMF_CYCLE, OPT_ARG_CYCLE),
 });
-
-static int next_unique_id_to_use = 0;
 
 struct chanspy_translation_helper {
 	/* spy data */
@@ -347,6 +390,12 @@
 	int volfactor;
 };
 
+struct spy_dtmf_options {
+	char exit;
+	char cycle;
+	char volume;
+};
+
 static void *spy_alloc(struct ast_channel *chan, void *data)
 {
 	/* just store the data pointer in the channel structure */
@@ -399,26 +448,20 @@
 	.generate = spy_generate,
 };
 
-static int start_spying(struct ast_channel *chan, const char *spychan_name, struct ast_audiohook *audiohook)
+static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook)
 {
 	int res = 0;
 	struct ast_channel *peer = NULL;
 
-	ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, chan->name);
-
-	res = ast_audiohook_attach(chan, audiohook);
-
-	if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) { 
+	ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, autochan->chan->name);
+
+	res = ast_audiohook_attach(autochan->chan, audiohook);
+
+	if (!res && ast_test_flag(autochan->chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(autochan->chan))) {
 		ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
 	}
 	return res;
 }
-
-struct chanspy_ds {
-	struct ast_channel *chan;
-	char unique_id[20];
-	ast_mutex_t lock;
-};
 
 static void change_spy_mode(const char digit, struct ast_flags *flags)
 {
@@ -434,8 +477,9 @@
 	}
 }
 
-static int channel_spy(struct ast_channel *chan, struct chanspy_ds *spyee_chanspy_ds, 
-	int *volfactor, int fd, struct ast_flags *flags, char *exitcontext) 
+static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_autochan,
+	int *volfactor, int fd, struct spy_dtmf_options *user_options, struct ast_flags *flags,
+	char *exitcontext)
 {
 	struct chanspy_translation_helper csth;
 	int running = 0, res, x = 0;
@@ -443,32 +487,22 @@
 	char *name;
 	struct ast_frame *f;
 	struct ast_silence_generator *silgen = NULL;
-	struct ast_channel *spyee = NULL, *spyee_bridge = NULL;
+	struct ast_autochan *spyee_bridge_autochan = NULL;
 	const char *spyer_name;
 
 	ast_channel_lock(chan);
 	spyer_name = ast_strdupa(chan->name);
 	ast_channel_unlock(chan);
 
-	ast_mutex_lock(&spyee_chanspy_ds->lock);
-	if (spyee_chanspy_ds->chan) {
-		spyee = spyee_chanspy_ds->chan;
-		ast_channel_lock(spyee);
-	}
-	ast_mutex_unlock(&spyee_chanspy_ds->lock);
-
-	if (!spyee) {
+	/* We now hold the channel lock on spyee */
+
+	if (ast_check_hangup(chan) || ast_check_hangup(spyee_autochan->chan)) {
 		return 0;
 	}
 
-	/* We now hold the channel lock on spyee */
-
-	if (ast_check_hangup(chan) || ast_check_hangup(spyee)) {
-		ast_channel_unlock(spyee);
-		return 0;
-	}
-
-	name = ast_strdupa(spyee->name);
+	ast_channel_lock(spyee_autochan->chan);
+	name = ast_strdupa(spyee_autochan->chan->name);
+	ast_channel_unlock(spyee_autochan->chan);
 
 	ast_verb(2, "Spying on channel %s\n", name);
 	manager_event(EVENT_FLAG_CALL, "ChanSpyStart",
@@ -480,26 +514,23 @@
 
 	ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy");
 
-	if (start_spying(spyee, spyer_name, &csth.spy_audiohook)) {
+	if (start_spying(spyee_autochan, spyer_name, &csth.spy_audiohook)) {
 		ast_audiohook_destroy(&csth.spy_audiohook);
-		ast_channel_unlock(spyee);
 		return 0;
 	}
 
- 	ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
+	ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
 	ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy");
-  	if (start_spying(spyee, spyer_name, &csth.whisper_audiohook)) {
-		ast_log(LOG_WARNING, "Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", spyee->name);
-	}
-	if ((spyee_bridge = ast_bridged_channel(spyee))) {
-		ast_channel_lock(spyee_bridge);
-		if (start_spying(spyee_bridge, spyer_name, &csth.bridge_whisper_audiohook)) {
-			ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee %s. Barge mode disabled!\n", spyee->name);
-		}
-		ast_channel_unlock(spyee_bridge);
-	}
-	ast_channel_unlock(spyee);
-	spyee = NULL;
+	if (start_spying(spyee_autochan, spyer_name, &csth.whisper_audiohook)) {
+		ast_log(LOG_WARNING, "Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", name);
+	}
+	if ((spyee_bridge_autochan = ast_autochan_setup(ast_bridged_channel(spyee_autochan->chan)))) {
+		ast_channel_lock(spyee_bridge_autochan->chan);
+		if (start_spying(spyee_bridge_autochan, spyer_name, &csth.bridge_whisper_audiohook)) {
+			ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee %s. Barge mode disabled!\n", name);
+		}
+		ast_channel_unlock(spyee_bridge_autochan->chan);
+	}
 
 	ast_channel_lock(chan);
 	ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
@@ -589,10 +620,13 @@
 			}
 		}
 
-		if (res == '*') {
+		if (res == user_options->cycle) {
 			running = 0;
 			break;
-		} else if (res == '#') {
+		} else if (res == user_options->exit) {
+			running = -2;
+			break;
+		} else if (res == user_options->volume) {
 			if (!ast_strlen_zero(inp)) {
 				running = atoi(inp);
 				break;
@@ -632,128 +666,45 @@
 	ast_audiohook_detach(&csth.spy_audiohook);
 	ast_audiohook_unlock(&csth.spy_audiohook);
 	ast_audiohook_destroy(&csth.spy_audiohook);
-	
+
+	if (spyee_bridge_autochan) {
+		ast_autochan_destroy(spyee_bridge_autochan);
+	}
+
 	ast_verb(2, "Done Spying on channel %s\n", name);
 	manager_event(EVENT_FLAG_CALL, "ChanSpyStop", "SpyeeChannel: %s\r\n", name);
 
 	return running;
 }
 
-/*!
- * \note This relies on the embedded lock to be recursive, as it may be called
- * due to a call to chanspy_ds_free with the lock held there.
- */
-static void chanspy_ds_destroy(void *data)
-{
-	struct chanspy_ds *chanspy_ds = data;
-
-	/* Setting chan to be NULL is an atomic operation, but we don't want this
-	 * value to change while this lock is held.  The lock is held elsewhere
-	 * while it performs non-atomic operations with this channel pointer */
-
-	ast_mutex_lock(&chanspy_ds->lock);
-	chanspy_ds->chan = NULL;
-	ast_mutex_unlock(&chanspy_ds->lock);
-}
-
-static void chanspy_ds_chan_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
-{
-	struct chanspy_ds *chanspy_ds = data;
-	
-	ast_mutex_lock(&chanspy_ds->lock);
-	chanspy_ds->chan = new_chan;
-	ast_mutex_unlock(&chanspy_ds->lock);
-}
-
-static const struct ast_datastore_info chanspy_ds_info = {
-	.type = "chanspy",
-	.destroy = chanspy_ds_destroy,
-	.chan_fixup = chanspy_ds_chan_fixup,
-};
-
-static struct chanspy_ds *chanspy_ds_free(struct chanspy_ds *chanspy_ds)
-{
-	if (!chanspy_ds)
-		return NULL;
-
-	ast_mutex_lock(&chanspy_ds->lock);
-	if (chanspy_ds->chan) {
-		struct ast_datastore *datastore;
-		struct ast_channel *chan;
-
-		chan = chanspy_ds->chan;
-
-		ast_channel_lock(chan);
-		if ((datastore = ast_channel_datastore_find(chan, &chanspy_ds_info, chanspy_ds->unique_id))) {
-			ast_channel_datastore_remove(chan, datastore);
-			/* chanspy_ds->chan is NULL after this call */
-			chanspy_ds_destroy(datastore->data);
-			datastore->data = NULL;
-			ast_datastore_free(datastore);
-		}
-		ast_channel_unlock(chan);
-	}
-	ast_mutex_unlock(&chanspy_ds->lock);
-
-	return NULL;
-}
-
-/*! \note Returns the channel in the chanspy_ds locked as well as the chanspy_ds locked */
-static struct chanspy_ds *setup_chanspy_ds(struct ast_channel *chan, struct chanspy_ds *chanspy_ds)
-{
-	struct ast_datastore *datastore = NULL;
-
-	ast_mutex_lock(&chanspy_ds->lock);
-
-	if (!(datastore = ast_datastore_alloc(&chanspy_ds_info, chanspy_ds->unique_id))) {
-		ast_mutex_unlock(&chanspy_ds->lock);
-		chanspy_ds = chanspy_ds_free(chanspy_ds);
-		ast_channel_unlock(chan);
-		return NULL;
-	}
-	
-	chanspy_ds->chan = chan;
-	datastore->data = chanspy_ds;
-	ast_channel_datastore_add(chan, datastore);
-
-	return chanspy_ds;
-}
-
-static struct chanspy_ds *next_channel(struct ast_channel *chan,
-	const struct ast_channel *last, const char *spec,
-	const char *exten, const char *context, struct chanspy_ds *chanspy_ds)
+static struct ast_autochan *next_channel(struct ast_channel_iterator *iter,
+		struct ast_autochan *autochan, struct ast_channel *chan)
 {
 	struct ast_channel *next;
 	const size_t pseudo_len = strlen("DAHDI/pseudo");
 
+	if (!iter) {
+		return NULL;
+	}
+
 redo:
-	if (!ast_strlen_zero(spec))
-		next = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
-	else if (!ast_strlen_zero(exten))
-		next = ast_walk_channel_by_exten_locked(last, exten, context);
-	else
-		next = ast_channel_walk_locked(last);
-
-	if (!next)
+	if (!(next = ast_channel_iterator_next(iter))) {
 		return NULL;
+	}
 
 	if (!strncmp(next->name, "DAHDI/pseudo", pseudo_len)) {
-		last = next;
-		ast_channel_unlock(next);
 		goto redo;
 	} else if (next == chan) {
-		last = next;
-		ast_channel_unlock(next);
 		goto redo;
 	}
 
-	return setup_chanspy_ds(next, chanspy_ds);
+	return ast_autochan_setup(next);
 }
 
 static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
-	int volfactor, const int fd, const char *mygroup, const char *myenforced,
-	const char *spec, const char *exten, const char *context, const char *mailbox,
-	const char *name_context)
+	int volfactor, const int fd, struct spy_dtmf_options *user_options,
+	const char *mygroup, const char *myenforced, const char *spec, const char *exten,
+	const char *context, const char *mailbox, const char *name_context)
 {
 	char nameprefix[AST_NAME_STRLEN];
 	char peer_name[AST_NAME_STRLEN + 5];
@@ -764,7 +715,7 @@
 	char *ptr;
 	int num;
 	int num_spyed_upon = 1;
-	struct chanspy_ds chanspy_ds = { 0, };
+	struct ast_channel_iterator *iter = NULL;
 
 	if (ast_test_flag(flags, OPTION_EXIT)) {
 		const char *c;
@@ -779,10 +730,6 @@
 		ast_channel_unlock(chan);
 	}
 
-	ast_mutex_init(&chanspy_ds.lock);
-
-	snprintf(chanspy_ds.unique_id, sizeof(chanspy_ds.unique_id), "%d", ast_atomic_fetchadd_int(&next_unique_id_to_use, +1));
-
 	if (chan->_state != AST_STATE_UP)
 		ast_answer(chan);
 
@@ -791,8 +738,8 @@
 	waitms = 100;
 
 	for (;;) {
-		struct chanspy_ds *peer_chanspy_ds = NULL, *next_chanspy_ds = NULL;
-		struct ast_channel *prev = NULL, *peer = NULL;
+		struct ast_autochan *autochan = NULL, *next_autochan = NULL;
+		struct ast_channel *prev = NULL;
 
 		if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) {
 			res = ast_streamfile(chan, "beep", chan->language);
@@ -813,6 +760,19 @@
 			}
 		}
 
+		/* Set up the iterator we'll be using during this call */
+		if (!ast_strlen_zero(spec)) {
+			iter = ast_channel_iterator_by_name_new(0, spec, strlen(spec));
+		} else if (!ast_strlen_zero(exten)) {
+			iter = ast_channel_iterator_by_exten_new(0, exten, context);
+		} else {
+			iter = ast_channel_iterator_all_new(0);
+		}
+
+		if (!iter) {
+			return -1;
+		}
+
 		res = ast_waitfordigit(chan, waitms);
 		if (res < 0) {
 			ast_clear_flag(chan, AST_FLAG_SPYING);
@@ -832,38 +792,30 @@
 		waitms = 100;
 		num_spyed_upon = 0;
 
-		for (peer_chanspy_ds = next_channel(chan, prev, spec, exten, context, &chanspy_ds);
-		     peer_chanspy_ds;
-			 chanspy_ds_free(peer_chanspy_ds), prev = peer,
-		     peer_chanspy_ds = next_chanspy_ds ? next_chanspy_ds : 
-			 	next_channel(chan, prev, spec, exten, context, &chanspy_ds), next_chanspy_ds = NULL) {
+		for (autochan = next_channel(iter, autochan, chan);
+		     autochan;
+			 prev = autochan->chan, ast_autochan_destroy(autochan),
+		     autochan = next_autochan ? next_autochan : 
+				next_channel(iter, autochan, chan), next_autochan = NULL) {
 			int igrp = !mygroup;
 			int ienf = !myenforced;
 			char *s;
 
-			peer = peer_chanspy_ds->chan;
-
-			ast_mutex_unlock(&peer_chanspy_ds->lock);
-
-			if (peer == prev) {
-				ast_channel_unlock(peer);
-				chanspy_ds_free(peer_chanspy_ds);
+			if (autochan->chan == prev) {
+				ast_autochan_destroy(autochan);
 				break;
 			}
 
 			if (ast_check_hangup(chan)) {
-				ast_channel_unlock(peer);
-				chanspy_ds_free(peer_chanspy_ds);
+				ast_autochan_destroy(autochan);
 				break;
 			}
 
-			if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(peer)) {
-				ast_channel_unlock(peer);
+			if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(autochan->chan)) {
 				continue;
 			}
 
-			if (ast_check_hangup(peer) || ast_test_flag(peer, AST_FLAG_SPYING)) {
-				ast_channel_unlock(peer);
+			if (ast_check_hangup(autochan->chan) || ast_test_flag(autochan->chan, AST_FLAG_SPYING)) {
 				continue;
 			}
 
@@ -874,14 +826,22 @@
 				char dup_mygroup[512];
 				char *groups[NUM_SPYGROUPS];
 				char *mygroups[NUM_SPYGROUPS];
-				const char *group;
+				const char *group = NULL;
 				int x;
 				int y;
 				ast_copy_string(dup_mygroup, mygroup, sizeof(dup_mygroup));
 				num_mygroups = ast_app_separate_args(dup_mygroup, ':', mygroups,
 					ARRAY_LEN(mygroups));
 
-				if ((group = pbx_builtin_getvar_helper(peer, "SPYGROUP"))) {
+				/* Before dahdi scan was part of chanspy, it would use the "GROUP" variable 
+				 * rather than "SPYGROUP", this check is done to preserve expected behavior */
+				if (ast_test_flag(flags, OPTION_DAHDI_SCAN)) {
+					group = pbx_builtin_getvar_helper(autochan->chan, "GROUP");
+				} else {
+					group = pbx_builtin_getvar_helper(autochan->chan, "SPYGROUP");
+				}
+
+				if (!ast_strlen_zero(group)) {
 					ast_copy_string(dup_group, group, sizeof(dup_group));
 					num_groups = ast_app_separate_args(dup_group, ':', groups,
 						ARRAY_LEN(groups));
@@ -898,10 +858,8 @@
 			}
 
 			if (!igrp) {
-				ast_channel_unlock(peer);
 				continue;
 			}
-
 			if (myenforced) {
 				char ext[AST_CHANNEL_NAME + 3];
 				char buffer[512];
@@ -909,7 +867,7 @@
 
 				snprintf(buffer, sizeof(buffer) - 1, ":%s:", myenforced);
 
-				ast_copy_string(ext + 1, peer->name, sizeof(ext) - 1);
+				ast_copy_string(ext + 1, autochan->chan->name, sizeof(ext) - 1);
 				if ((end = strchr(ext, '-'))) {
 					*end++ = ':';
 					*end = '\0';
@@ -927,18 +885,13 @@
 			}
 
 			strcpy(peer_name, "spy-");
-			strncat(peer_name, peer->name, AST_NAME_STRLEN - 4 - 1);
+			strncat(peer_name, autochan->chan->name, AST_NAME_STRLEN - 4 - 1);
 			ptr = strchr(peer_name, '/');
 			*ptr++ = '\0';
 			ptr = strsep(&ptr, "-");
 
 			for (s = peer_name; s < ptr; s++)
 				*s = tolower(*s);
-			/* We have to unlock the peer channel here to avoid a deadlock.
-			 * So, when we need to dereference it again, we have to lock the 
-			 * datastore and get the pointer from there to see if the channel 
-			 * is still valid. */
-			ast_channel_unlock(peer);
 
 			if (!ast_test_flag(flags, OPTION_QUIET)) {
 				if (ast_test_flag(flags, OPTION_NAME)) {
@@ -954,7 +907,7 @@
 								res = ast_waitstream(chan, "");
 							}
 							if (res) {
-								chanspy_ds_free(peer_chanspy_ds);
+								ast_autochan_destroy(autochan);
 								break;
 							}
 						} else {
@@ -966,42 +919,38 @@
 				}
 			}
 
-			res = channel_spy(chan, peer_chanspy_ds, &volfactor, fd, flags, exitcontext);
-			num_spyed_upon++;	
+			res = channel_spy(chan, autochan, &volfactor, fd, user_options, flags, exitcontext);
+			num_spyed_upon++;
 
 			if (res == -1) {
-				chanspy_ds_free(peer_chanspy_ds);
+				ast_autochan_destroy(autochan);
 				goto exit;
 			} else if (res == -2) {
 				res = 0;
-				chanspy_ds_free(peer_chanspy_ds);
+				ast_autochan_destroy(autochan);
 				goto exit;
 			} else if (res > 1 && spec) {
 				struct ast_channel *next;
 
 				snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);
 
-				if ((next = ast_get_channel_by_name_prefix_locked(nameprefix, strlen(nameprefix)))) {
-					peer_chanspy_ds = chanspy_ds_free(peer_chanspy_ds);
-					next_chanspy_ds = setup_chanspy_ds(next, &chanspy_ds);
+				if ((next = ast_channel_get_by_name_prefix(nameprefix, strlen(nameprefix)))) {
+					next_autochan = ast_autochan_setup(next);
+					next = ast_channel_unref(next);
 				} else {
 					/* stay on this channel, if it is still valid */
-
-					ast_mutex_lock(&peer_chanspy_ds->lock);
-					if (peer_chanspy_ds->chan) {
-						ast_channel_lock(peer_chanspy_ds->chan);
-						next_chanspy_ds = peer_chanspy_ds;
-						peer_chanspy_ds = NULL;
+					if (!ast_check_hangup(autochan->chan)) {
+						next_autochan = ast_autochan_setup(autochan->chan);
 					} else {
 						/* the channel is gone */
-						ast_mutex_unlock(&peer_chanspy_ds->lock);
-						next_chanspy_ds = NULL;
+						next_autochan = NULL;
 					}
 				}
-
-				peer = NULL;
-			}
-		}
+			}
+		}
+
+		iter = ast_channel_iterator_destroy(iter);
+
 		if (res == -1 || ast_check_hangup(chan))
 			break;
 	}
@@ -1010,10 +959,6 @@
 	ast_clear_flag(chan, AST_FLAG_SPYING);
 
 	ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
-
-	ast_mutex_lock(&chanspy_ds.lock);
-	ast_mutex_unlock(&chanspy_ds.lock);
-	ast_mutex_destroy(&chanspy_ds.lock);
 
 	return res;
 }
@@ -1025,6 +970,11 @@
 	char *recbase = NULL;
 	int fd = 0;
 	struct ast_flags flags;
+	struct spy_dtmf_options user_options = {
+		.cycle = '*',
+		.volume = '#',
+		.exit = '\0',
+	};
 	int oldwf = 0;
 	int volfactor = 0;
 	int res;
@@ -1043,6 +993,7 @@
 		args.spec = NULL;
 
 	if (args.options) {
+		char tmp;
 		ast_app_parse_options(spy_opts, &flags, opts, args.options);
 		if (ast_test_flag(&flags, OPTION_GROUP))
 			mygroup = opts[OPT_ARG_GROUP];
@@ -1050,6 +1001,24 @@
 		if (ast_test_flag(&flags, OPTION_RECORD) &&
 			!(recbase = opts[OPT_ARG_RECORD]))
 			recbase = "chanspy";
+
+		if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
+			tmp = opts[OPT_ARG_EXIT][0];
+			if (strchr("0123456789*#", tmp) && tmp != '\0') {
+				user_options.exit = tmp;
+			} else {
+				ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.");
+			}
+		}
+
+		if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
+			tmp = opts[OPT_ARG_CYCLE][0];
+			if (strchr("0123456789*#", tmp) && tmp != '\0') {
+				user_options.cycle = tmp;
+			} else {
+				ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.");
+			}
+		}
 
 		if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
 			int vol;
@@ -1065,7 +1034,7 @@
 
 		if (ast_test_flag(&flags, OPTION_ENFORCED))
 			myenforced = opts[OPT_ARG_ENFORCED];
-		
+
 		if (ast_test_flag(&flags, OPTION_NAME)) {
 			if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
 				char *delimiter;
@@ -1078,10 +1047,9 @@
 				}
 			}
 		}
-
-
-	} else
+	} else {
 		ast_clear_flag(&flags, AST_FLAGS_ALL);
+	}
 
 	oldwf = chan->writeformat;
 	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
@@ -1099,7 +1067,7 @@
 		}
 	}
 
-	res = common_exec(chan, &flags, volfactor, fd, mygroup, myenforced, args.spec, NULL, NULL, mailbox, name_context);
+	res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, myenforced, args.spec, NULL, NULL, mailbox, name_context);
 
 	if (fd)
 		close(fd);
@@ -1117,6 +1085,11 @@
 	char *recbase = NULL;
 	int fd = 0;
 	struct ast_flags flags;
+	struct spy_dtmf_options user_options = {
+		.cycle = '*',
+		.volume = '#',
+		.exit = '\0',
+	};
 	int oldwf = 0;
 	int volfactor = 0;
 	int res;
@@ -1141,6 +1114,7 @@
 
 	if (args.options) {
 		char *opts[OPT_ARG_ARRAY_SIZE];
+		char tmp;
 
 		ast_app_parse_options(spy_opts, &flags, opts, args.options);
 		if (ast_test_flag(&flags, OPTION_GROUP))
@@ -1149,6 +1123,24 @@
 		if (ast_test_flag(&flags, OPTION_RECORD) &&
 			!(recbase = opts[OPT_ARG_RECORD]))
 			recbase = "chanspy";
+
+		if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
+			tmp = opts[OPT_ARG_EXIT][0];
+			if (strchr("0123456789*#", tmp) && tmp != '\0') {
+				user_options.exit = tmp;
+			} else {
+				ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.");
+			}
+		}
+
+		if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
+			tmp = opts[OPT_ARG_CYCLE][0];
+			if (strchr("0123456789*#", tmp) && tmp != '\0') {
+				user_options.cycle = tmp;
+			} else {
+				ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.");
+			}
+		}
 
 		if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
 			int vol;
@@ -1162,7 +1154,6 @@
 		if (ast_test_flag(&flags, OPTION_PRIVATE))
 			ast_set_flag(&flags, OPTION_WHISPER);
 
-		
 		if (ast_test_flag(&flags, OPTION_NAME)) {
 			if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
 				char *delimiter;
@@ -1176,8 +1167,9 @@
 			}
 		}
 
-	} else
+	} else {
 		ast_clear_flag(&flags, AST_FLAGS_ALL);
+	}
 
 	oldwf = chan->writeformat;
 	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
@@ -1196,10 +1188,46 @@
 	}
 
 
-	res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, exten, args.context, mailbox, name_context);
+	res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, NULL, NULL, exten, args.context, mailbox, name_context);
 
 	if (fd)
 		close(fd);
+
+	if (oldwf && ast_set_write_format(chan, oldwf) < 0)
+		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
+
+	return res;
+}
+
+static int dahdiscan_exec(struct ast_channel *chan, void *data)
+{
+	const char *spec = "DAHDI";
+	struct ast_flags flags;
+	struct spy_dtmf_options user_options = {
+		.cycle = '#',
+		.volume = '\0',
+		.exit = '*',
+	};
+	int oldwf = 0;
+	int res;
+	char *mygroup = NULL;
+
+	ast_clear_flag(&flags, AST_FLAGS_ALL);
+
+	if (!ast_strlen_zero(data)) {
+		mygroup = ast_strdupa(data);
+	}
+	ast_set_flag(&flags, OPTION_DTMF_EXIT);
+	ast_set_flag(&flags, OPTION_DTMF_CYCLE);
+	ast_set_flag(&flags, OPTION_DAHDI_SCAN);
+
+	oldwf = chan->writeformat;
+	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
+		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
+		return -1;
+	}
+
+	res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);
 
 	if (oldwf && ast_set_write_format(chan, oldwf) < 0)
 		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
@@ -1213,6 +1241,7 @@
 
 	res |= ast_unregister_application(app_chan);
 	res |= ast_unregister_application(app_ext);
+	res |= ast_unregister_application(app_dahdiscan);
 
 	return res;
 }
@@ -1223,6 +1252,7 @@
 
 	res |= ast_register_application_xml(app_chan, chanspy_exec);
 	res |= ast_register_application_xml(app_ext, extenspy_exec);
+	res |= ast_register_application_xml(app_dahdiscan, dahdiscan_exec);
 
 	return res;
 }

Modified: team/tilghman/str_substitution/apps/app_directed_pickup.c
URL: http://svn.digium.com/svn-view/asterisk/team/tilghman/str_substitution/apps/app_directed_pickup.c?view=diff&rev=191095&r1=191094&r2=191095
==============================================================================
--- team/tilghman/str_substitution/apps/app_directed_pickup.c (original)
+++ team/tilghman/str_substitution/apps/app_directed_pickup.c Wed Apr 29 12:31:24 2009
@@ -135,17 +135,35 @@
 		return 0;
 }
 
+struct pickup_by_name_args {
+	const char *name;
+	size_t len;
+};
+
+static int pickup_by_name_cb(void *obj, void *arg, void *data, int flags)
+{
+	struct ast_channel *chan = obj;
+	struct pickup_by_name_args *args = data;
+
+	ast_channel_lock(chan);
+	if (!strncasecmp(chan->name, args->name, args->len) && can_pickup(chan)) {
+		/* Return with the channel still locked on purpose */
+		return CMP_MATCH | CMP_STOP;
+	}
+	ast_channel_unlock(chan);
+
+	return 0;
+}
+
 /*! \brief Helper Function to walk through ALL channels checking NAME and STATE */
 static struct ast_channel *my_ast_get_channel_by_name_locked(const char *channame)
 {
-	struct ast_channel *chan;
 	char *chkchan;
-	size_t channame_len, chkchan_len;
-
-	channame_len = strlen(channame);
-	chkchan_len = channame_len + 2;
-
- 	chkchan = alloca(chkchan_len);
+	struct pickup_by_name_args pickup_args;
+
+	pickup_args.len = strlen(channame) + 2;
+
+	chkchan = alloca(pickup_args.len);
 
 	/* need to append a '-' for the comparison so we check full channel name,
 	 * i.e SIP/hgc- , use a temporary variable so original stays the same for
@@ -154,15 +172,9 @@
 	strcpy(chkchan, channame);
 	strcat(chkchan, "-");
 
-	for (chan = ast_walk_channel_by_name_prefix_locked(NULL, channame, channame_len);
-		 chan;
-		 chan = ast_walk_channel_by_name_prefix_locked(chan, channame, channame_len)) {
-		if (!strncasecmp(chan->name, chkchan, chkchan_len) && can_pickup(chan)) {
-			return chan;
-		}
-		ast_channel_unlock(chan);
-	}
-	return NULL;
+	pickup_args.name = chkchan;
+
+	return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0);
 }
 
 /*! \brief Attempt to pick up specified channel named , does not use context */
@@ -171,76 +183,82 @@
 	int res = 0;
 	struct ast_channel *target;
 

[... 6964 lines stripped ...]



More information about the svn-commits mailing list