[svn-commits] qwell: branch qwell/http-channels-post r390847 - in /team/qwell/http-channels...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jun 7 09:39:23 CDT 2013


Author: qwell
Date: Fri Jun  7 09:39:03 2013
New Revision: 390847

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=390847
Log:
Multiple revisions 390698,390701,390728-390730,390733-390734,390751,390771,390787,390803-390804,390830

........
  r390698 | qwell | 2013-06-06 14:44:45 -0500 (Thu, 06 Jun 2013) | 4 lines
  
  Convert message_router routes to ao2.  Add support for removal.
  
  Review: https://reviewboard.asterisk.org/r/2591/
........
  r390701 | qwell | 2013-06-06 14:51:12 -0500 (Thu, 06 Jun 2013) | 7 lines
  
  Split AGI manager events, to remove SubEvent field.
  
  This moves them to stasis, in the process.
  
  (closes issue ASTERISK-21470)
  Review: https://reviewboard.asterisk.org/r/2587/
........
  r390728 | kmoore | 2013-06-06 15:30:56 -0500 (Thu, 06 Jun 2013) | 1 line
  
  Fix documentation that was in review during the great suffix/prefix swap
........
  r390729 | qwell | 2013-06-06 15:32:15 -0500 (Thu, 06 Jun 2013) | 4 lines
  
  Remove props that people will yell at me for.
  
  I'm sorry I broke automerge. :(
........
  r390730 | kmoore | 2013-06-06 15:37:48 -0500 (Thu, 06 Jun 2013) | 4 lines
  
  Fix documentation generation
  
  Regression from r390701
........
  r390733 | rmudgett | 2013-06-06 15:47:10 -0500 (Thu, 06 Jun 2013) | 4 lines
  
  * Fix a couple missed hook installs that need AST_BRIDGE_HOOK_REMOVE_ON_PULL.
  
  * Rename some hook flag parameters to remove_flags.
........
  r390734 | rmudgett | 2013-06-06 15:50:25 -0500 (Thu, 06 Jun 2013) | 1 line
  
  Fix compiler warning.
........
  r390751 | mmichelson | 2013-06-06 16:40:35 -0500 (Thu, 06 Jun 2013) | 21 lines
  
  Refactor the features configuration scheme.
  
  Features configuration is handled in its own API in
  features_config.h and features_config.c. This way, features
  configuration is accessible to anything that needs it.
  
  In addition, features configuration has been altered to
  be more channel-oriented. Most callers of features API
  code will be supplying a channel so that the individual
  channel's settings will be acquired rather than the global
  setting.
  
  Missing from this commit is XML documentation for the
  features configuration. That will be handled in a separate
  commit.
  
  Review: https://reviewboard.asterisk.org/r/2578/
  
  (issue ASTERISK-21542)
........
  r390771 | rmudgett | 2013-06-06 17:46:54 -0500 (Thu, 06 Jun 2013) | 30 lines
  
  Reimplement bridging and DTMF features related channel variables in the bridging core.
  
  * The channel variable ATTENDED_TRANSFER_COMPLETE_SOUND is no longer
  channel driver specific.  If the channel variable is set on the
  transferrer channel, the sound will be played to the target of an attended
  transfer.
  
  * The channel variable BRIDGEPEER becomes a comma separated list of peers
  in a multi-party bridge.  The BRIDGEPEER value can have a maximum of 10
  peers listed.  Any more peers in the bridge will not be included in the
  list.  BRIDGEPEER is not valid in holding bridges like parking since those
  channels do not talk to each other even though they are in a bridge.
  
  * The channel variable BRIDGEPVTCALLID is only valid for two party bridges
  and will contain a value if the BRIDGEPEER's channel driver supports it.
  
  * The channel variable DYNAMIC_PEERNAME is redundant with BRIDGEPEER and
  is removed.  The more useful DYNAMIC_WHO_ACTIVATED gives the channel name
  that activated the dynamic feature.
  
  * The channel variables DYNAMIC_FEATURENAME and DYNAMIC_WHO_ACTIVATED are
  set only on the channel executing the dynamic feature.  Executing a
  dynamic feature on the bridge peer in a multi-party bridge will execute it
  on all peers of the activating channel.
  
  (closes issue ASTERISK-21555)
  Reported by: Matt Jordan
  
  Review: https://reviewboard.asterisk.org/r/2582/
........
  r390787 | mmichelson | 2013-06-06 18:32:13 -0500 (Thu, 06 Jun 2013) | 8 lines
  
  Conditionally reject duplicate entries in applicationmap containers.
  
  When reading from a config file, it's important to reject duplicates. Otherwise,
  featuregroups will have ambiguity when pointing to applicationmap items. However,
  when constructing the channel's current applicationmap, we don't care about duplicate
  names since it's the DTMF that identifies a feature, not the name.
........
  r390803 | rmudgett | 2013-06-06 19:33:20 -0500 (Thu, 06 Jun 2013) | 8 lines
  
  Tweak applicationmap and featuregroup config containers.
  
  * Change applicationmap and featuregroup to replace duplicate config items
  rather than reject them.
  
  * Remove some unneeded warning messages when getting the applicationmap
  allows duplicates from DYNAMIC_FEATURES.
........
  r390804 | rmudgett | 2013-06-06 20:06:49 -0500 (Thu, 06 Jun 2013) | 10 lines
  
  Refactor chan_dahdi/sig_analog/sig_pri and chan_misdn to use the common transfer functions.
  
  (closes issue ASTERISK-21523)
  Reported by: Matt Jordan
  
  (closes issue ASTERISK-21524)
  Reported by: Matt Jordan
  
  Review: https://reviewboard.asterisk.org/r/2600/
........
  r390830 | kmoore | 2013-06-07 07:56:56 -0500 (Fri, 07 Jun 2013) | 16 lines
  
  Rework stasis cache clear events
  
  Stasis cache clear message payloads now consist of a stasis_message
  representative of the message to be cleared from the cache. This allows
  multiple parallel caches to coexist and be cleared properly by the same
  cache clear message even when keyed on different fields.
  
  This change fixes a bug where multiple cache clears could be posted for
  channels. The cache clear is now produced in the destructor instead of
  ast_hangup.
  
  Additionally, dummy channels are no longer capable of producing channel
  snapshots.
  
  Review: https://reviewboard.asterisk.org/r/2596
........

Merged revisions 390698,390701,390728-390730,390733-390734,390751,390771,390787,390803-390804,390830 from http://svn.asterisk.org/svn/asterisk/trunk

Added:
    team/qwell/http-channels-post/include/asterisk/features_config.h
      - copied unchanged from r390830, trunk/include/asterisk/features_config.h
    team/qwell/http-channels-post/main/features_config.c
      - copied unchanged from r390830, trunk/main/features_config.c
Modified:
    team/qwell/http-channels-post/   (props changed)
    team/qwell/http-channels-post/CHANGES
    team/qwell/http-channels-post/UPGRADE.txt
    team/qwell/http-channels-post/apps/app_bridgewait.c
    team/qwell/http-channels-post/apps/app_dial.c
    team/qwell/http-channels-post/bridges/bridge_builtin_features.c
    team/qwell/http-channels-post/channels/chan_dahdi.c
    team/qwell/http-channels-post/channels/chan_mgcp.c
    team/qwell/http-channels-post/channels/chan_misdn.c
    team/qwell/http-channels-post/channels/chan_sip.c
    team/qwell/http-channels-post/channels/chan_unistim.c
    team/qwell/http-channels-post/channels/sig_analog.c
    team/qwell/http-channels-post/channels/sig_pri.c
    team/qwell/http-channels-post/channels/sig_pri.h
    team/qwell/http-channels-post/channels/sip/include/sip.h
    team/qwell/http-channels-post/configs/chan_dahdi.conf.sample
    team/qwell/http-channels-post/configs/iax.conf.sample
    team/qwell/http-channels-post/configs/sip.conf.sample
    team/qwell/http-channels-post/configs/skinny.conf.sample
    team/qwell/http-channels-post/include/asterisk/bridging.h
    team/qwell/http-channels-post/include/asterisk/bridging_features.h
    team/qwell/http-channels-post/include/asterisk/channel.h
    team/qwell/http-channels-post/include/asterisk/features.h
    team/qwell/http-channels-post/include/asterisk/stasis.h
    team/qwell/http-channels-post/include/asterisk/stasis_message_router.h
    team/qwell/http-channels-post/main/bridging.c
    team/qwell/http-channels-post/main/channel.c
    team/qwell/http-channels-post/main/endpoints.c
    team/qwell/http-channels-post/main/features.c
    team/qwell/http-channels-post/main/manager.c
    team/qwell/http-channels-post/main/stasis_cache.c
    team/qwell/http-channels-post/main/stasis_channels.c
    team/qwell/http-channels-post/main/stasis_message_router.c
    team/qwell/http-channels-post/res/parking/parking_manager.c
    team/qwell/http-channels-post/res/res_agi.c
    team/qwell/http-channels-post/tests/test_stasis.c

Propchange: team/qwell/http-channels-post/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/qwell/http-channels-post/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri Jun  7 09:39:03 2013
@@ -1,1 +1,1 @@
-/trunk:1-390688
+/trunk:1-390846

Modified: team/qwell/http-channels-post/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/qwell/http-channels-post/CHANGES?view=diff&rev=390847&r1=390846&r2=390847
==============================================================================
--- team/qwell/http-channels-post/CHANGES (original)
+++ team/qwell/http-channels-post/CHANGES Fri Jun  7 09:39:03 2013
@@ -106,6 +106,13 @@
    core, and is now two events: Hold and Unhold.  The status field has been
    removed.
 
+AGI (Asterisk Gateway Interface)
+------------------
+ * The manager event AGIExec has been split into AGIExecStart and AGIExecEnd.
+
+ * The manager event AsyncAGI has been split into AsyncAGIStart, AsyncAGIExec,
+   and AsyncAGIEnd.
+
 Channel Drivers
 ------------------
  * When a channel driver is configured to enable jiterbuffers, they are now
@@ -233,6 +240,31 @@
    reason to any string. It also allows for custom strings to be read as the
    redirecting reason from SIP Diversion headers.
 
+ * For DTMF blind and attended transfers, the channel variable TRANSFER_CONTEXT
+   must be on the channel initiating the transfer to have any effect.
+
+ * The channel variable ATTENDED_TRANSFER_COMPLETE_SOUND is no longer channel
+   driver specific.  If the channel variable is set on the transferrer channel,
+   the sound will be played to the target of an attended transfer.
+
+ * The channel variable BRIDGEPEER becomes a comma separated list of peers in
+   a multi-party bridge.  The BRIDGEPEER value can have a maximum of 10 peers
+   listed.  Any more peers in the bridge will not be included in the list.
+   BRIDGEPEER is not valid in holding bridges like parking since those channels
+   do not talk to each other even though they are in a bridge.
+
+ * The channel variable BRIDGEPVTCALLID is only valid for two party bridges
+   and will contain a value if the BRIDGEPEER's channel driver supports it.
+
+ * The channel variable DYNAMIC_PEERNAME is redundant with BRIDGEPEER and is
+   removed.  The more useful DYNAMIC_WHO_ACTIVATED gives the channel name that
+   activated the dynamic feature.
+
+ * The channel variables DYNAMIC_FEATURENAME and DYNAMIC_WHO_ACTIVATED are set
+   only on the channel executing the dynamic feature.  Executing a dynamic
+   feature on the bridge peer in a multi-party bridge will execute it on all
+   peers of the activating channel.
+
 Realtime
 ------------------
  * Dynamic realtime tables for SIP Users can now include a 'path' field. This
@@ -240,7 +272,7 @@
    tables can also use the 'supportpath' field to enable Path header support.
 
  * LDAP realtime configurations for SIP Users now have the AstAccountPathSupport
-   objectIdentifier. This maps to the supportpath option in sip.conf. 
+   objectIdentifier. This maps to the supportpath option in sip.conf.
 
 RTP
 ------------------

Modified: team/qwell/http-channels-post/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/qwell/http-channels-post/UPGRADE.txt?view=diff&rev=390847&r1=390846&r2=390847
==============================================================================
--- team/qwell/http-channels-post/UPGRADE.txt (original)
+++ team/qwell/http-channels-post/UPGRADE.txt Fri Jun  7 09:39:03 2013
@@ -37,6 +37,11 @@
 CEL:
  - The Uniqueid field for a channel is now a stable identifier, and will not
    change due to transfers, parking, etc.
+
+Core:
+ - The following channel variables have changed behavior which is described in
+   the CHANGES file: TRANSFER_CONTEXT, BRIDGEPEER, BRIDGEPVTCALLID,
+   ATTENDED_TRANSFER_COMPLETE_SOUND, DYNAMIC_FEATURENAME, and DYNAMIC_PEERNAME.
 
 Queues:
  - Queue logging for PAUSEALL/UNPAUSEALL now only occurs if the interface this is
@@ -86,9 +91,12 @@
 
 Features:
  - The features.conf [applicationmap] <FeatureName>  ActivatedBy option is
-   no longer honored.  The feature is activated by which channel
-   DYNAMIC_FEATURES includes the feature is on.  Use predial to set different
-   values of DYNAMIC_FEATURES on the channels
+   no longer honored.  The feature is always activated by the channel that has
+   DYNAMIC_FEATURES defined on it when it enters the bridge.  Use predial to set
+   different values of DYNAMIC_FEATURES on the channels
+
+ - Executing a dynamic feature on the bridge peer in a multi-party bridge will
+   execute it on all peers of the activating channel.
 
 Parking:
  - The arguments for the Park, ParkedCall, and ParkAndAnnounce applications have

Modified: team/qwell/http-channels-post/apps/app_bridgewait.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/http-channels-post/apps/app_bridgewait.c?view=diff&rev=390847&r1=390846&r2=390847
==============================================================================
--- team/qwell/http-channels-post/apps/app_bridgewait.c (original)
+++ team/qwell/http-channels-post/apps/app_bridgewait.c Fri Jun  7 09:39:03 2013
@@ -141,7 +141,7 @@
 
 	/* Limits struct holds time as milliseconds, so muliply 1000x */
 	hold_limits.duration *= 1000;
-	ast_bridge_features_set_limits(features, &hold_limits, 1 /* remove_on_pull */);
+	ast_bridge_features_set_limits(features, &hold_limits, AST_BRIDGE_HOOK_REMOVE_ON_PULL);
 	ast_bridge_features_limits_destroy(&hold_limits);
 
 	return 0;

Modified: team/qwell/http-channels-post/apps/app_dial.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/http-channels-post/apps/app_dial.c?view=diff&rev=390847&r1=390846&r2=390847
==============================================================================
--- team/qwell/http-channels-post/apps/app_dial.c (original)
+++ team/qwell/http-channels-post/apps/app_dial.c Fri Jun  7 09:39:03 2013
@@ -69,6 +69,7 @@
 #include "asterisk/dial.h"
 #include "asterisk/stasis_channels.h"
 #include "asterisk/bridging.h"
+#include "asterisk/features_config.h"
 
 /*** DOCUMENTATION
 	<application name="Dial" language="en_US">
@@ -1074,7 +1075,7 @@
 	int caller_entertained = outgoing
 		&& ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
 	struct ast_party_connected_line connected_caller;
-	struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1);
+	struct ast_str *featurecode = ast_str_alloca(AST_FEATURE_MAX_LEN + 1);
 	int cc_recall_core_id;
 	int is_cc_recall;
 	int cc_frame_received = 0;
@@ -1701,22 +1702,31 @@
 
 static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str **featurecode)
 {
-	struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */
-	struct ast_call_feature feature = { 0, };
+	char disconnect_code[AST_FEATURE_MAX_LEN];
 	int res;
 
 	ast_str_append(featurecode, 1, "%c", code);
 
-	res = ast_feature_detect(chan, &features, ast_str_buffer(*featurecode), &feature);
-
-	if (res != AST_FEATURE_RETURN_STOREDIGITS) {
+	res = ast_get_builtin_feature(chan, "disconnect", disconnect_code, sizeof(disconnect_code));
+	if (res) {
 		ast_str_reset(*featurecode);
-	}
-	if (feature.feature_mask & AST_FEATURE_DISCONNECT) {
-		return 1;
-	}
-
-	return 0;
+		return 0;
+	}
+
+	if (strlen(disconnect_code) > ast_str_strlen(*featurecode)) {
+		/* Could be a partial match, anyway */
+		if (strncmp(disconnect_code, ast_str_buffer(*featurecode), ast_str_strlen(*featurecode))) {
+			ast_str_reset(*featurecode);
+		}
+		return 0;
+	}
+
+	if (strcmp(disconnect_code, ast_str_buffer(*featurecode))) {
+		ast_str_reset(*featurecode);
+		return 0;
+	}
+
+	return 1;
 }
 
 /* returns true if there is a valid privacy reply */

Modified: team/qwell/http-channels-post/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/http-channels-post/bridges/bridge_builtin_features.c?view=diff&rev=390847&r1=390846&r2=390847
==============================================================================
--- team/qwell/http-channels-post/bridges/bridge_builtin_features.c (original)
+++ team/qwell/http-channels-post/bridges/bridge_builtin_features.c Fri Jun  7 09:39:03 2013
@@ -49,6 +49,7 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/pbx.h"
 #include "asterisk/parking.h"
+#include "asterisk/features_config.h"
 
 /*!
  * \brief Helper function that presents dialtone and grabs extension
@@ -59,6 +60,18 @@
 static int grab_transfer(struct ast_channel *chan, char *exten, size_t exten_len, const char *context)
 {
 	int res;
+	int digit_timeout;
+	RAII_VAR(struct ast_features_xfer_config *, xfer_cfg, NULL, ao2_cleanup);
+
+	ast_channel_lock(chan);
+	xfer_cfg = ast_get_chan_features_xfer_config(chan);
+	if (!xfer_cfg) {
+		ast_log(LOG_ERROR, "Unable to get transfer configuration\n");
+		ast_channel_unlock(chan);
+		return -1;
+	}
+	digit_timeout = xfer_cfg->transferdigittimeout;
+	ast_channel_unlock(chan);
 
 	/* Play the simple "transfer" prompt out and wait */
 	res = ast_stream_and_wait(chan, "pbx-transfer", AST_DIGIT_ANY);
@@ -73,8 +86,7 @@
 	}
 
 	/* Drop to dialtone so they can enter the extension they want to transfer to */
-/* BUGBUG the timeout needs to be configurable from features.conf. */
-	res = ast_app_dtget(chan, context, exten, exten_len, exten_len - 1, 3000);
+	res = ast_app_dtget(chan, context, exten, exten_len, exten_len - 1, digit_timeout);
 	if (res < 0) {
 		/* Hangup or error */
 		res = -1;
@@ -122,6 +134,9 @@
 		return NULL;
 	}
 
+	/* Who is transferring the call. */
+	pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", ast_channel_name(caller));
+
 	/* Before we actually dial out let's inherit appropriate information. */
 	copy_caller_data(chan, caller);
 
@@ -263,8 +278,14 @@
 	struct ast_bridge_features caller_features;
 	int xfer_failed;
 	struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
+	const char *complete_sound;
 	const char *context;
 	enum atxfer_code transfer_code = ATXFER_INCOMPLETE;
+	const char *atxfer_abort;
+	const char *atxfer_threeway;
+	const char *atxfer_complete;
+	const char *fail_sound;
+	RAII_VAR(struct ast_features_xfer_config *, xfer_cfg, NULL, ao2_cleanup);
 
 	ast_bridge_channel_write_hold(bridge_channel, NULL);
 
@@ -273,6 +294,22 @@
 	ast_channel_lock(bridge_channel->chan);
 	context = ast_strdupa(get_transfer_context(bridge_channel->chan,
 		attended_transfer ? attended_transfer->context : NULL));
+	xfer_cfg = ast_get_chan_features_xfer_config(bridge_channel->chan);
+	if (!xfer_cfg) {
+		ast_log(LOG_ERROR, "Unable to get transfer configuration options\n");
+		ast_channel_unlock(bridge_channel->chan);
+		return 0;
+	}
+	if (attended_transfer) {
+		atxfer_abort = ast_strdupa(S_OR(attended_transfer->abort, xfer_cfg->atxferabort));
+		atxfer_threeway = ast_strdupa(S_OR(attended_transfer->threeway, xfer_cfg->atxferthreeway));
+		atxfer_complete = ast_strdupa(S_OR(attended_transfer->complete, xfer_cfg->atxfercomplete));
+	} else {
+		atxfer_abort = ast_strdupa(xfer_cfg->atxferabort);
+		atxfer_threeway = ast_strdupa(xfer_cfg->atxferthreeway);
+		atxfer_complete = ast_strdupa(xfer_cfg->atxfercomplete);
+	}
+	fail_sound = ast_strdupa(xfer_cfg->xferfailsound);
 	ast_channel_unlock(bridge_channel->chan);
 
 	/* Grab the extension to transfer to */
@@ -288,36 +325,27 @@
 	if (!peer) {
 		ast_bridge_merge_inhibit(bridge, -1);
 		ao2_ref(bridge, -1);
-/* BUGBUG beeperr needs to be configurable from features.conf */
-		ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
-		ast_bridge_channel_write_unhold(bridge_channel);
-		return 0;
-	}
-
-/* BUGBUG bridging API features does not support features.conf featuremap */
+		ast_stream_and_wait(bridge_channel->chan, fail_sound, AST_DIGIT_NONE);
+		ast_bridge_channel_write_unhold(bridge_channel);
+		return 0;
+	}
+
 /* BUGBUG bridging API features does not support the features.conf atxfer bounce between C & B channels */
 	/* Setup a DTMF menu to control the transfer. */
 	if (ast_bridge_features_init(&caller_features)
 		|| ast_bridge_hangup_hook(&caller_features,
 			attended_transfer_complete, &transfer_code, NULL, 0)
-		|| ast_bridge_dtmf_hook(&caller_features,
-			attended_transfer && !ast_strlen_zero(attended_transfer->abort)
-				? attended_transfer->abort : "*1",
+		|| ast_bridge_dtmf_hook(&caller_features, atxfer_abort,
 			attended_transfer_abort, &transfer_code, NULL, 0)
-		|| ast_bridge_dtmf_hook(&caller_features,
-			attended_transfer && !ast_strlen_zero(attended_transfer->complete)
-				? attended_transfer->complete : "*2",
+		|| ast_bridge_dtmf_hook(&caller_features, atxfer_complete,
 			attended_transfer_complete, &transfer_code, NULL, 0)
-		|| ast_bridge_dtmf_hook(&caller_features,
-			attended_transfer && !ast_strlen_zero(attended_transfer->threeway)
-				? attended_transfer->threeway : "*3",
+		|| ast_bridge_dtmf_hook(&caller_features, atxfer_threeway,
 			attended_transfer_threeway, &transfer_code, NULL, 0)) {
 		ast_bridge_features_cleanup(&caller_features);
 		ast_hangup(peer);
 		ast_bridge_merge_inhibit(bridge, -1);
 		ao2_ref(bridge, -1);
-/* BUGBUG beeperr needs to be configurable from features.conf */
-		ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
+		ast_stream_and_wait(bridge_channel->chan, fail_sound, AST_DIGIT_NONE);
 		ast_bridge_channel_write_unhold(bridge_channel);
 		return 0;
 	}
@@ -330,8 +358,7 @@
 		ast_hangup(peer);
 		ast_bridge_merge_inhibit(bridge, -1);
 		ao2_ref(bridge, -1);
-/* BUGBUG beeperr needs to be configurable from features.conf */
-		ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
+		ast_stream_and_wait(bridge_channel->chan, fail_sound, AST_DIGIT_NONE);
 		ast_bridge_channel_write_unhold(bridge_channel);
 		return 0;
 	}
@@ -345,8 +372,7 @@
 		ast_hangup(peer);
 		ast_bridge_merge_inhibit(bridge, -1);
 		ao2_ref(bridge, -1);
-/* BUGBUG beeperr needs to be configurable from features.conf */
-		ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
+		ast_stream_and_wait(bridge_channel->chan, fail_sound, AST_DIGIT_NONE);
 		ast_bridge_channel_write_unhold(bridge_channel);
 		return 0;
 	}
@@ -385,6 +411,20 @@
 	ast_bridge_destroy(attended_bridge);
 	ast_bridge_features_cleanup(&caller_features);
 
+	/* Is there a courtesy sound to play to the peer? */
+	ast_channel_lock(bridge_channel->chan);
+	complete_sound = pbx_builtin_getvar_helper(bridge_channel->chan,
+		"ATTENDED_TRANSFER_COMPLETE_SOUND");
+	if (!ast_strlen_zero(complete_sound)) {
+		complete_sound = ast_strdupa(complete_sound);
+	} else {
+		complete_sound = NULL;
+	}
+	ast_channel_unlock(bridge_channel->chan);
+	if (complete_sound) {
+		pbx_builtin_setvar_helper(peer, "BRIDGE_PLAY_SOUND", complete_sound);
+	}
+
 	xfer_failed = -1;
 	switch (transfer_code) {
 	case ATXFER_INCOMPLETE:
@@ -415,7 +455,7 @@
 	if (xfer_failed) {
 		ast_hangup(peer);
 		if (!ast_check_hangup_locked(bridge_channel->chan)) {
-			ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
+			ast_stream_and_wait(bridge_channel->chan, fail_sound, AST_DIGIT_NONE);
 		}
 		ast_bridge_channel_write_unhold(bridge_channel);
 	}

Modified: team/qwell/http-channels-post/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/http-channels-post/channels/chan_dahdi.c?view=diff&rev=390847&r1=390846&r2=390847
==============================================================================
--- team/qwell/http-channels-post/channels/chan_dahdi.c (original)
+++ team/qwell/http-channels-post/channels/chan_dahdi.c Fri Jun  7 09:39:03 2013
@@ -130,6 +130,8 @@
 #include "asterisk/paths.h"
 #include "asterisk/ccss.h"
 #include "asterisk/data.h"
+#include "asterisk/features_config.h"
+#include "asterisk/bridging.h"
 
 /*** DOCUMENTATION
 	<application name="DAHDISendKeypadFacility" language="en_US">
@@ -7840,55 +7842,49 @@
 
 static void *analog_ss_thread(void *data);
 
+/*!
+ * \internal
+ * \brief Attempt to transfer 3-way call.
+ *
+ * \param p DAHDI private structure.
+ *
+ * \note On entry these locks are held: real-call, private, 3-way call.
+ * \note On exit these locks are held: real-call, private.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
 static int attempt_transfer(struct dahdi_pvt *p)
 {
-	/* In order to transfer, we need at least one of the channels to
-	   actually be in a call bridge.  We can't conference two applications
-	   together (but then, why would we want to?) */
-	if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
-		/* The three-way person we're about to transfer to could still be in MOH, so
-		   stop it now */
-		ast_queue_unhold(p->subs[SUB_THREEWAY].owner);
-		if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RINGING) {
-			ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_RINGING);
-		}
-		if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RING) {
-			tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
-		}
-		 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
-			ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
-					ast_channel_name(ast_bridged_channel(p->subs[SUB_REAL].owner)), ast_channel_name(p->subs[SUB_THREEWAY].owner));
-			return -1;
-		}
-		/* Orphan the channel after releasing the lock */
-		ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
-		unalloc_sub(p, SUB_THREEWAY);
-	} else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
-		ast_queue_unhold(p->subs[SUB_REAL].owner);
-		if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RINGING) {
-			ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_RINGING);
-		}
-		if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RING) {
-			tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
-		}
-		if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
-			ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
-					ast_channel_name(ast_bridged_channel(p->subs[SUB_THREEWAY].owner)), ast_channel_name(p->subs[SUB_REAL].owner));
-			return -1;
-		}
-		/* Three-way is now the REAL */
-		swap_subs(p, SUB_THREEWAY, SUB_REAL);
-		ast_channel_unlock(p->subs[SUB_REAL].owner);
-		unalloc_sub(p, SUB_THREEWAY);
-		/* Tell the caller not to hangup */
-		return 1;
-	} else {
-		ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
-			ast_channel_name(p->subs[SUB_REAL].owner), ast_channel_name(p->subs[SUB_THREEWAY].owner));
-		ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
-		return -1;
-	}
-	return 0;
+	struct ast_channel *owner_real;
+	struct ast_channel *owner_3way;
+	enum ast_transfer_result xfer_res;
+	int res = 0;
+
+	owner_real = ast_channel_ref(p->subs[SUB_REAL].owner);
+	owner_3way = ast_channel_ref(p->subs[SUB_THREEWAY].owner);
+
+	ast_verb(3, "TRANSFERRING %s to %s\n",
+		ast_channel_name(owner_3way), ast_channel_name(owner_real));
+
+	ast_channel_unlock(owner_real);
+	ast_channel_unlock(owner_3way);
+	ast_mutex_unlock(&p->lock);
+
+	xfer_res = ast_bridge_transfer_attended(owner_3way, owner_real);
+	if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
+		ast_softhangup(owner_3way, AST_SOFTHANGUP_DEV);
+		res = -1;
+	}
+
+	/* Must leave with these locked. */
+	ast_channel_lock(owner_real);
+	ast_mutex_lock(&p->lock);
+
+	ast_channel_unref(owner_real);
+	ast_channel_unref(owner_3way);
+
+	return res;
 }
 
 static int check_for_conference(struct dahdi_pvt *p)
@@ -8398,17 +8394,13 @@
 								p->owner = NULL;
 								/* Ring the phone */
 								dahdi_ring_phone(p);
-							} else {
-								if ((res = attempt_transfer(p)) < 0) {
-									ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
-									if (p->subs[SUB_THREEWAY].owner)
-										ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
-								} else if (res) {
-									/* Don't actually hang up at this point */
-									if (p->subs[SUB_THREEWAY].owner)
-										ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
-									break;
-								}
+							} else if (!attempt_transfer(p)) {
+								/*
+								 * Transfer successful.  Don't actually hang up at this point.
+								 * Let our channel legs of the calls die off as the transfer
+								 * percolates through the core.
+								 */
+								break;
 							}
 						} else {
 							ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
@@ -10137,15 +10129,15 @@
 	return 0;
 }
 
-static int canmatch_featurecode(const char *exten)
+static int canmatch_featurecode(const char *pickupexten, const char *exten)
 {
 	int extlen = strlen(exten);
-	const char *pickup_ext;
+
 	if (!extlen) {
 		return 1;
 	}
-	pickup_ext = ast_pickup_ext();
-	if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
+
+	if (extlen < strlen(pickupexten) && !strncmp(pickupexten, exten, extlen)) {
 		return 1;
 	}
 	/* hardcoded features are *60, *67, *69, *70, *72, *73, *78, *79, *82, *0 */
@@ -10191,6 +10183,8 @@
 	int res;
 	int idx;
 	struct ast_format tmpfmt;
+	RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
+	const char *pickupexten;
 
 	ast_mutex_lock(&ss_thread_lock);
 	ss_thread_count++;
@@ -10210,6 +10204,17 @@
 		ast_hangup(chan);
 		goto quit;
 	}
+
+	ast_channel_lock(chan);
+	pickup_cfg = ast_get_chan_features_pickup_config(chan);
+	if (!pickup_cfg) {
+		ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
+		pickupexten = "";
+	} else {
+		pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+	}
+	ast_channel_unlock(chan);
+
 	if (p->dsp)
 		ast_dsp_digitreset(p->dsp);
 	switch (p->sig) {
@@ -10576,7 +10581,7 @@
 				memset(exten, 0, sizeof(exten));
 				timeout = firstdigittimeout;
 
-			} else if (!strcmp(exten,ast_pickup_ext())) {
+			} else if (!strcmp(exten, pickupexten)) {
 				/* Scan all channels and see if there are any
 				 * ringing channels that have call groups
 				 * that equal this channels pickup group
@@ -10708,7 +10713,7 @@
 				}
 			} else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
 				S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
-				&& !canmatch_featurecode(exten)) {
+				&& !canmatch_featurecode(pickupexten, exten)) {
 				ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
 					S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
 					ast_channel_context(chan));

Modified: team/qwell/http-channels-post/channels/chan_mgcp.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/http-channels-post/channels/chan_mgcp.c?view=diff&rev=390847&r1=390846&r2=390847
==============================================================================
--- team/qwell/http-channels-post/channels/chan_mgcp.c (original)
+++ team/qwell/http-channels-post/channels/chan_mgcp.c Fri Jun  7 09:39:03 2013
@@ -84,6 +84,7 @@
 #include "asterisk/pktccops.h"
 #include "asterisk/stasis.h"
 #include "asterisk/bridging.h"
+#include "asterisk/features_config.h"
 
 /*
  * Define to work around buggy dlink MGCP phone firmware which
@@ -2971,8 +2972,20 @@
 	int res= 0;
 	int getforward = 0;
 	int loop_pause = 100;
+	RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
+	const char *pickupexten;
 
 	len = strlen(p->dtmf_buf);
+
+	ast_channel_lock(chan);
+	pickup_cfg = ast_get_chan_features_pickup_config(chan);
+	if (!pickup_cfg) {
+		ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
+		pickupexten = "";
+	} else {
+		pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+	}
+	ast_channel_unlock(chan);
 
 	while (len < AST_MAX_EXTENSION - 1) {
 		ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name);
@@ -3065,7 +3078,7 @@
 			len = 0;
 			memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
 			timeout = firstdigittimeout;
-		} else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) {
+		} else if (!strcmp(p->dtmf_buf, pickupexten)) {
 			/* Scan all channels and see if any there
 			 * ringing channqels with that have call groups
 			 * that equal this channels pickup group

Modified: team/qwell/http-channels-post/channels/chan_misdn.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/http-channels-post/channels/chan_misdn.c?view=diff&rev=390847&r1=390846&r2=390847
==============================================================================
--- team/qwell/http-channels-post/channels/chan_misdn.c (original)
+++ team/qwell/http-channels-post/channels/chan_misdn.c Fri Jun  7 09:39:03 2013
@@ -102,6 +102,8 @@
 #include "asterisk/causes.h"
 #include "asterisk/format.h"
 #include "asterisk/format_cap.h"
+#include "asterisk/features_config.h"
+#include "asterisk/bridging.h"
 
 #include "chan_misdn_config.h"
 #include "isdn_lib.h"
@@ -8591,10 +8593,9 @@
 static int misdn_attempt_transfer(struct chan_list *active_ch, struct chan_list *held_ch)
 {
 	int retval;
-	struct ast_channel *target;
-	struct ast_channel *transferee;
-	struct ast_party_connected_line target_colp;
-	struct ast_party_connected_line transferee_colp;
+	enum ast_transfer_result xfer_res;
+	struct ast_channel *to_target;
+	struct ast_channel *to_transferee;
 
 	switch (active_ch->state) {
 	case MISDN_PROCEEDING:
@@ -8607,59 +8608,24 @@
 	}
 
 	ast_channel_lock_both(held_ch->ast, active_ch->ast);
-
-	transferee = ast_bridged_channel(held_ch->ast);
-	if (!transferee) {
-		/*
-		 * Could not transfer.  Held channel is not bridged anymore.
-		 * Held party probably got tired of waiting and hung up.
-		 */
-		ast_channel_unlock(held_ch->ast);
-		ast_channel_unlock(active_ch->ast);
-		return -1;
-	}
-
-	target = active_ch->ast;
+	to_target = active_ch->ast;
+	to_transferee = held_ch->ast;
 	chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
-		ast_channel_name(held_ch->ast), ast_channel_name(target));
-
-	ast_party_connected_line_init(&target_colp);
-	ast_party_connected_line_copy(&target_colp, ast_channel_connected(target));
-
-	/* Reset any earlier private connected id representation */
-	ast_party_id_reset(&target_colp.priv);
-
-	ast_party_connected_line_init(&transferee_colp);
-	ast_party_connected_line_copy(&transferee_colp, ast_channel_connected(held_ch->ast));
-
-	/* Reset any earlier private connected id representation*/
-	ast_party_id_reset(&transferee_colp.priv);
-
+		ast_channel_name(to_transferee), ast_channel_name(to_target));
 	held_ch->hold.state = MISDN_HOLD_TRANSFER;
-
-	/*
-	 * Before starting a masquerade, all channel and pvt locks must
-	 * be unlocked.  Any recursive channel locks held before
-	 * ast_channel_transfer_masquerade() invalidates deadlock
-	 * avoidance.  Since we are unlocking both the pvt and its owner
-	 * channel it is possible for "target" and "transferee" to be
-	 * destroyed by their pbx threads.  To prevent this we must give
-	 * "target" and "transferee" a reference before any unlocking
-	 * takes place.
-	 */
-	ao2_ref(target, +1);
-	ao2_ref(transferee, +1);
-	ast_channel_unlock(held_ch->ast);
-	ast_channel_unlock(active_ch->ast);
-
-	/* Setup transfer masquerade. */
-	retval = ast_channel_transfer_masquerade(target, &target_colp, 0,
-		transferee, &transferee_colp, 1);
-
-	ast_party_connected_line_free(&target_colp);
-	ast_party_connected_line_free(&transferee_colp);
-	ao2_ref(target, -1);
-	ao2_ref(transferee, -1);
+	ast_channel_ref(to_target);
+	ast_channel_ref(to_transferee);
+	ast_channel_unlock(to_target);
+	ast_channel_unlock(to_transferee);
+
+	retval = 0;
+	xfer_res = ast_bridge_transfer_attended(to_transferee, to_target);
+	if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
+		retval = -1;
+	}
+
+	ast_channel_unref(to_target);
+	ast_channel_unref(to_transferee);
 	return retval;
 }
 
@@ -10071,6 +10037,9 @@
 		}
 
 		if (ch->state == MISDN_WAITING4DIGS) {
+			RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
+			const char *pickupexten;
+
 			/*  Ok, incomplete Setup, waiting till extension exists */
 			if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
 				chan_misdn_log(1, bc->port, " --> using keypad as info\n");
@@ -10080,8 +10049,18 @@
 			strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
 			ast_channel_exten_set(ch->ast, bc->dialed.number);
 
+			ast_channel_lock(ch->ast);
+			pickup_cfg = ast_get_chan_features_pickup_config(ch->ast);
+			if (!pickup_cfg) {
+				ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
+				pickupexten = "";
+			} else {
+				pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+			}
+			ast_channel_unlock(ch->ast);
+
 			/* Check for Pickup Request first */
-			if (!strcmp(ast_channel_exten(ch->ast), ast_pickup_ext())) {
+			if (!strcmp(ast_channel_exten(ch->ast), pickupexten)) {
 				if (ast_pickup_call(ch->ast)) {
 					hangup_chan(ch, bc);
 				} else {
@@ -10169,6 +10148,8 @@
 		int ai;
 		int im;
 		int append_msn = 0;
+		RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
+		const char *pickupexten;
 
 		if (ch) {
 			switch (ch->state) {
@@ -10223,6 +10204,16 @@
 			ast_log(LOG_ERROR, "cb_events: misdn_new failed!\n");
 			return RESPONSE_RELEASE_SETUP;
 		}
+
+		ast_channel_lock(chan);
+		pickup_cfg = ast_get_chan_features_pickup_config(chan);
+		if (!pickup_cfg) {
+			ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
+			pickupexten = "";
+		} else {
+			pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+		}
+		ast_channel_unlock(chan);
 
 		if ((exceed = add_in_calls(bc->port))) {
 			char tmp[16];
@@ -10315,7 +10306,7 @@
 		}
 
 		/* Check for Pickup Request first */
-		if (!strcmp(ast_channel_exten(chan), ast_pickup_ext())) {
+		if (!strcmp(ast_channel_exten(chan), pickupexten)) {
 			if (!ch->noautorespond_on_setup) {
 				/* Sending SETUP_ACK */
 				misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);

Modified: team/qwell/http-channels-post/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/http-channels-post/channels/chan_sip.c?view=diff&rev=390847&r1=390846&r2=390847
==============================================================================
--- team/qwell/http-channels-post/channels/chan_sip.c (original)
+++ team/qwell/http-channels-post/channels/chan_sip.c Fri Jun  7 09:39:03 2013
@@ -296,6 +296,7 @@
 #include "asterisk/app.h"
 #include "asterisk/bridging.h"
 #include "asterisk/stasis_endpoints.h"
+#include "asterisk/features_config.h"
 
 /*** DOCUMENTATION
 	<application name="SIPDtmfMode" language="en_US">
@@ -17662,6 +17663,16 @@
 	char tmpf[256] = "", *from = NULL;
 	struct sip_request *req;
 	char *decoded_uri;
+	RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, ast_get_chan_features_pickup_config(p->owner), ao2_cleanup);
+	const char *pickupexten;
+
+	if (!pickup_cfg) {
+		ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
+		pickupexten = "";
+	} else {
+		/* Don't need to duplicate since channel is locked for the duration of this function */
+		pickupexten = pickup_cfg->pickupexten;
+	}
 
 	req = oreq;
 	if (!req) {
@@ -17772,7 +17783,7 @@
 			return SIP_GET_DEST_EXTEN_FOUND;
 		}

[... 6650 lines stripped ...]



More information about the svn-commits mailing list