[svn-commits] mmichelson: branch mmichelson/features_config r390384 - in /team/mmichelson/f...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Jun 3 15:04:29 CDT 2013


Author: mmichelson
Date: Mon Jun  3 15:04:26 2013
New Revision: 390384

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=390384
Log:
Address review feedback from Richard.


Modified:
    team/mmichelson/features_config/bridges/bridge_builtin_features.c
    team/mmichelson/features_config/channels/chan_dahdi.c
    team/mmichelson/features_config/channels/chan_mgcp.c
    team/mmichelson/features_config/channels/chan_misdn.c
    team/mmichelson/features_config/channels/chan_sip.c
    team/mmichelson/features_config/channels/chan_unistim.c
    team/mmichelson/features_config/channels/sig_analog.c
    team/mmichelson/features_config/include/asterisk/bridging_features.h
    team/mmichelson/features_config/include/asterisk/channel.h
    team/mmichelson/features_config/include/asterisk/features_config.h
    team/mmichelson/features_config/main/bridging.c
    team/mmichelson/features_config/main/features.c
    team/mmichelson/features_config/main/features_config.c
    team/mmichelson/features_config/main/manager.c

Modified: team/mmichelson/features_config/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/bridges/bridge_builtin_features.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/bridges/bridge_builtin_features.c (original)
+++ team/mmichelson/features_config/bridges/bridge_builtin_features.c Mon Jun  3 15:04:26 2013
@@ -65,6 +65,10 @@
 
 	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");
+		return -1;
+	}
 	digit_timeout = xfer_cfg->transferdigittimeout;
 	ast_channel_unlock(chan);
 
@@ -286,9 +290,19 @@
 	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);
-	atxfer_abort = ast_strdupa(xfer_cfg->atxferabort);
-	atxfer_threeway = ast_strdupa(xfer_cfg->atxferthreeway);
-	atxfer_complete = ast_strdupa(xfer_cfg->atxfercomplete);
+	if (!xfer_cfg) {
+		ast_log(LOG_ERROR, "Unable to get transfer configuration options\n");
+		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);
 

Modified: team/mmichelson/features_config/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/channels/chan_dahdi.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/channels/chan_dahdi.c (original)
+++ team/mmichelson/features_config/channels/chan_dahdi.c Mon Jun  3 15:04:26 2013
@@ -10215,7 +10215,12 @@
 
 	ast_channel_lock(chan);
 	pickup_cfg = ast_get_chan_features_pickup_config(chan);
-	pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+	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)

Modified: team/mmichelson/features_config/channels/chan_mgcp.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/channels/chan_mgcp.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/channels/chan_mgcp.c (original)
+++ team/mmichelson/features_config/channels/chan_mgcp.c Mon Jun  3 15:04:26 2013
@@ -2979,7 +2979,12 @@
 
 	ast_channel_lock(chan);
 	pickup_cfg = ast_get_chan_features_pickup_config(chan);
-	pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+	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) {

Modified: team/mmichelson/features_config/channels/chan_misdn.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/channels/chan_misdn.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/channels/chan_misdn.c (original)
+++ team/mmichelson/features_config/channels/chan_misdn.c Mon Jun  3 15:04:26 2013
@@ -10086,7 +10086,12 @@
 
 			ast_channel_lock(ch->ast);
 			pickup_cfg = ast_get_chan_features_pickup_config(ch->ast);
-			pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+			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 */
@@ -10237,7 +10242,12 @@
 
 		ast_channel_lock(chan);
 		pickup_cfg = ast_get_chan_features_pickup_config(chan);
-		pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+		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))) {

Modified: team/mmichelson/features_config/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/channels/chan_sip.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/channels/chan_sip.c (original)
+++ team/mmichelson/features_config/channels/chan_sip.c Mon Jun  3 15:04:26 2013
@@ -17664,6 +17664,15 @@
 	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) {
@@ -17774,7 +17783,7 @@
 			return SIP_GET_DEST_EXTEN_FOUND;
 		}
 		if (ast_exists_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from))
-			|| !strcmp(decoded_uri, pickup_cfg->pickupexten)) {
+			|| !strcmp(decoded_uri, pickupexten)) {
 			if (!oreq) {
 				ast_string_field_set(p, exten, decoded_uri);
 			}
@@ -17802,7 +17811,7 @@
 	if (ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP)
 		&& (ast_canmatch_extension(NULL, p->context, uri, 1, S_OR(p->cid_num, from))
 			|| ast_canmatch_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from))
-			|| !strncmp(decoded_uri, pickup_cfg->pickupexten, strlen(decoded_uri)))) {
+			|| !strncmp(decoded_uri, pickupexten, strlen(decoded_uri)))) {
 		/* Overlap dialing is enabled and we need more digits to match an extension. */
 		return SIP_GET_DEST_EXTEN_MATCHMORE;
 	}
@@ -25651,6 +25660,14 @@
 	if (c) {	/* We have a call  -either a new call or an old one (RE-INVITE) */
 		enum ast_channel_state c_state = ast_channel_state(c);
 		RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, ast_get_chan_features_pickup_config(c), 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 {
+			pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+		}
 
 		if (c_state != AST_STATE_UP && reinvite &&
 			(p->invitestate == INV_TERMINATED || p->invitestate == INV_CONFIRMED)) {
@@ -25672,7 +25689,7 @@
 			transmit_provisional_response(p, "100 Trying", req, 0);
 			p->invitestate = INV_PROCEEDING;
 			ast_setstate(c, AST_STATE_RING);
-			if (strcmp(p->exten, pickup_cfg->pickupexten)) {	/* Call to extension -start pbx on this call */
+			if (strcmp(p->exten, pickupexten)) {	/* Call to extension -start pbx on this call */
 				enum ast_pbx_result result;
 
 				result = ast_pbx_start(c);

Modified: team/mmichelson/features_config/channels/chan_unistim.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/channels/chan_unistim.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/channels/chan_unistim.c (original)
+++ team/mmichelson/features_config/channels/chan_unistim.c Mon Jun  3 15:04:26 2013
@@ -3097,11 +3097,13 @@
 		if (c) {
 			ast_channel_lock(c);
 			pickup_cfg = ast_get_chan_features_pickup_config(c);
-			pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+			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(c);
-		} else {
-			pickup_cfg = ast_get_chan_features_pickup_config(NULL);
-			pickupexten = ast_strdupa(pickup_cfg->pickupexten);
 		}
 		if (c && !strcmp(s->device->phone_number, pickupexten)) {
 			if (unistimdebug) {
@@ -4115,6 +4117,11 @@
 			/* XXX Is there a way to get a specific channel here? */
 			RAII_VAR(struct ast_features_pickup_config *, pickup_cfg,
 					ast_get_chan_features_pickup_config(NULL), ao2_cleanup);
+
+			if (!pickup_cfg) {
+				ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
+				break;
+			}
 
 			pte->device->selected = -1;
 			ast_copy_string(pte->device->phone_number, pickup_cfg->pickupexten,

Modified: team/mmichelson/features_config/channels/sig_analog.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/channels/sig_analog.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/channels/sig_analog.c (original)
+++ team/mmichelson/features_config/channels/sig_analog.c Mon Jun  3 15:04:26 2013
@@ -1790,7 +1790,12 @@
 
 	ast_channel_lock(chan);
 	pickup_cfg = ast_get_chan_features_pickup_config(chan);
-	pickupexten = ast_strdupa(pickup_cfg->pickupexten);
+	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);
 
 	analog_dsp_reset_and_flush_digits(p);

Modified: team/mmichelson/features_config/include/asterisk/bridging_features.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/include/asterisk/bridging_features.h?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/include/asterisk/bridging_features.h (original)
+++ team/mmichelson/features_config/include/asterisk/bridging_features.h Mon Jun  3 15:04:26 2013
@@ -256,6 +256,12 @@
 /* BUGBUG the context should be figured out based upon TRANSFER_CONTEXT channel variable of A/B or current context of A/B. More appropriate for when channel moved to other bridges. */
 	/*! Context to use for transfers */
 	char context[AST_MAX_CONTEXT];
+	/*! DTMF string used to abort the transfer */
+	char abort[MAXIMUM_DTMF_FEATURE_STRING];
+	/*! DTMF string used to turn the transfer into a three way conference */
+	char threeway[MAXIMUM_DTMF_FEATURE_STRING];
+	/*! DTMF string used to complete the transfer */
+	char complete[MAXIMUM_DTMF_FEATURE_STRING];
 };
 
 /*!

Modified: team/mmichelson/features_config/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/include/asterisk/channel.h?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/include/asterisk/channel.h (original)
+++ team/mmichelson/features_config/include/asterisk/channel.h Mon Jun  3 15:04:26 2013
@@ -927,8 +927,8 @@
 	AST_FEATURE_AUTOMIXMON =   (1 << 6),
 };
 
-#define AST_FEATURE_DTMF_MASK AST_FEATURE_REDIRECT | AST_FEATURE_DISCONNECT |\
-	AST_FEATURE_ATXFER | AST_FEATURE_AUTOMON | AST_FEATURE_PARKCALL | AST_FEATURE_AUTOMIXMON
+#define AST_FEATURE_DTMF_MASK (AST_FEATURE_REDIRECT | AST_FEATURE_DISCONNECT |\
+	AST_FEATURE_ATXFER | AST_FEATURE_AUTOMON | AST_FEATURE_PARKCALL | AST_FEATURE_AUTOMIXMON)
 
 /*! \brief bridge configuration */
 struct ast_bridge_config {

Modified: team/mmichelson/features_config/include/asterisk/features_config.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/include/asterisk/features_config.h?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/include/asterisk/features_config.h (original)
+++ team/mmichelson/features_config/include/asterisk/features_config.h Mon Jun  3 15:04:26 2013
@@ -50,9 +50,9 @@
  */
 struct ast_features_xfer_config {
 	AST_DECLARE_STRING_FIELDS (
-		/*! Sound to play to transferee when transfer succeeds */
+		/*! Sound to play when transfer succeeds */
 		AST_STRING_FIELD(xfersound);
-		/*! Sound to play to transferee when transfer fails */
+		/*! Sound to play when transfer fails */
 		AST_STRING_FIELD(xferfailsound);
 		/*! DTMF sequence used to abort an attempted atxfer */
 		AST_STRING_FIELD(atxferabort);
@@ -227,4 +227,4 @@
 
 int ast_features_config_init(void);
 
-#endif // _FEATURES_CONFIG_H
+#endif /* _FEATURES_CONFIG_H */

Modified: team/mmichelson/features_config/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/main/bridging.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/main/bridging.c (original)
+++ team/mmichelson/features_config/main/bridging.c Mon Jun  3 15:04:26 2013
@@ -1920,6 +1920,10 @@
 
 	ast_channel_lock(bridge_channel->chan);
 	gen_cfg = ast_get_chan_features_general_config(bridge_channel->chan);
+	if (!gen_cfg) {
+		ast_log(LOG_ERROR, "Unable to retrieve features configuration.\n");
+		return;
+	}
 	digit_timeout = gen_cfg->featuredigittimeout;
 	ast_channel_unlock(bridge_channel->chan);
 

Modified: team/mmichelson/features_config/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/main/features.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/main/features.c (original)
+++ team/mmichelson/features_config/main/features.c Mon Jun  3 15:04:26 2013
@@ -75,6 +75,8 @@
 #include "asterisk/bridging.h"
 #include "asterisk/bridging_basic.h"
 #include "asterisk/features_config.h"
+
+#undef TEST_FRAMEWORK
 
 /*
  * Party A - transferee
@@ -795,67 +797,6 @@
 }
 
 #if 0
-/*!
- * \brief Check goto on transfer
- * \param chan
- *
- * Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
- * When found make sure the types are compatible. Check if channel is valid
- * if so start the new channel else hangup the call.
- */
-static void check_goto_on_transfer(struct ast_channel *chan)
-{
-	struct ast_channel *xferchan;
-	const char *val;
-	char *goto_on_transfer;
-	char *x;
-
-	ast_channel_lock(chan);
-	val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
-	if (ast_strlen_zero(val)) {
-		ast_channel_unlock(chan);
-		return;
-	}
-	goto_on_transfer = ast_strdupa(val);
-	ast_channel_unlock(chan);
-
-	ast_debug(1, "Attempting GOTO_ON_BLINDXFR=%s for %s.\n", val, ast_channel_name(chan));
-
-	xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", ast_channel_linkedid(chan), 0,
-		"%s", ast_channel_name(chan));
-	if (!xferchan) {
-		return;
-	}
-
-	/* Make formats okay */
-	ast_format_copy(ast_channel_readformat(xferchan), ast_channel_readformat(chan));
-	ast_format_copy(ast_channel_writeformat(xferchan), ast_channel_writeformat(chan));
-
-	if (ast_channel_masquerade(xferchan, chan)) {
-		/* Failed to setup masquerade. */
-		ast_hangup(xferchan);
-		return;
-	}
-
-	for (x = goto_on_transfer; *x; ++x) {
-		if (*x == '^') {
-			*x = ',';
-		}
-	}
-	ast_parseable_goto(xferchan, goto_on_transfer);
-	ast_channel_state_set(xferchan, AST_STATE_UP);
-	ast_clear_flag(ast_channel_flags(xferchan), AST_FLAGS_ALL);
-	ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
-
-	ast_do_masquerade(xferchan);
-	if (ast_pbx_start(xferchan)) {
-		/* Failed to start PBX. */
-		ast_hangup(xferchan);
-	}
-}
-#endif
-
-#if 0
 static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
 	const char *caller_name, struct ast_channel *requestor,
 	struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, const char *addr,
@@ -2263,128 +2204,6 @@
 
 #if 0
 /*!
- * \brief Blind transfer user to another extension
- * \param chan channel to be transfered
- * \param peer channel initiated blind transfer
- * \param config
- * \param code
- * \param data
- * \param sense  feature options
- *
- * Place chan on hold, check if transferred to parkinglot extension,
- * otherwise check extension exists and transfer caller.
- * \retval AST_FEATURE_RETURN_SUCCESS.
- * \retval -1 on failure.
- */
-static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
-{
-	struct ast_channel *transferer;
-	struct ast_channel *transferee;
-	struct ast_exten *park_exten;
-	const char *transferer_real_context;
-	char xferto[256] = "";
-	int res;
-	RAII_VAR(struct ast_features_xfer_config *, xfer_cfg, NULL, ao2_cleanup);
-
-	ast_debug(1, "Executing Blind Transfer %s, %s (sense=%d) \n", ast_channel_name(chan), ast_channel_name(peer), sense);
-	set_peers(&transferer, &transferee, peer, chan, sense);
-	transferer_real_context = ast_strdupa(real_ctx(transferer, transferee));
-
-	/* Start autoservice on transferee while we talk to the transferer */
-	ast_autoservice_start(transferee);
-	ast_indicate(transferee, AST_CONTROL_HOLD);
-
-	/* Transfer */
-	res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
-	if (res < 0) {
-		finishup(transferee);
-		return -1; /* error ? */
-	}
-	if (res > 0) { /* If they've typed a digit already, handle it */
-		xferto[0] = (char) res;
-	}
-
-	ast_channel_lock(transferer);
-	xfer_cfg = ast_get_chan_features_xfer_config(transferer);
-	ast_channel_unlock(transferer);
-
-	/* XXX All accesses to xfer_cfg after this point are not thread-safe,
-	 * but I don't care because this is dead code
-	 */
-
-	res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, xfer_cfg->transferdigittimeout);
-	if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
-		finishup(transferee);
-		return -1;
-	}
-	if (res == 0) {
-		if (xferto[0]) {
-			ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
-				xferto, transferer_real_context);
-		} else {
-			/* Does anyone care about this case? */
-			ast_log(LOG_WARNING, "No digits dialed.\n");
-		}
-		ast_stream_and_wait(transferer, "pbx-invalid", "");
-		finishup(transferee);
-		return AST_FEATURE_RETURN_SUCCESS;
-	}
-
-	park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
-	if (park_exten) {
-		/* We are transfering the transferee to a parking lot. */
-		return xfer_park_call_helper(transferee, transferer, park_exten);
-	}
-
-	/* Do blind transfer. */
-	ast_verb(3, "Blind transferring %s to '%s' (context %s) priority 1\n",
-		ast_channel_name(transferee), xferto, transferer_real_context);
-	ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
-	pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", ast_channel_name(transferee));
-	pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", ast_channel_name(transferer));
-	finishup(transferee);
-	ast_channel_lock(transferer);
-	if (!ast_channel_cdr(transferer)) {
-		/* this code should never get called (in a perfect world) */
-		ast_channel_cdr_set(transferer, ast_cdr_alloc());
-		if (ast_channel_cdr(transferer)) {
-			ast_cdr_init(ast_channel_cdr(transferer), transferer); /* initialize our channel's cdr */
-			ast_cdr_start(ast_channel_cdr(transferer));
-		}
-	}
-	ast_channel_unlock(transferer);
-	if (ast_channel_cdr(transferer)) {
-		struct ast_cdr *swap = ast_channel_cdr(transferer);
-
-		ast_debug(1,
-			"transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
-			ast_channel_name(transferer), ast_channel_name(transferee), ast_channel_cdr(transferer)->lastapp,
-			ast_channel_cdr(transferer)->lastdata, ast_channel_cdr(transferer)->channel,
-			ast_channel_cdr(transferer)->dstchannel);
-		ast_debug(1, "TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
-			ast_channel_cdr(transferee)->lastapp, ast_channel_cdr(transferee)->lastdata, ast_channel_cdr(transferee)->channel,
-			ast_channel_cdr(transferee)->dstchannel);
-		ast_debug(1, "transferer_real_context=%s; xferto=%s\n",
-			transferer_real_context, xferto);
-		/* swap cdrs-- it will save us some time & work */
-		ast_channel_cdr_set(transferer, ast_channel_cdr(transferee));
-		ast_channel_cdr_set(transferee, swap);
-	}
-
-	res = ast_channel_pbx(transferee) ? AST_FEATURE_RETURN_SUCCESSBREAK : -1;
-
-	/* Doh!  Use our handy async_goto functions */
-	if (ast_async_goto(transferee, transferer_real_context, xferto, 1)) {
-		ast_log(LOG_WARNING, "Async goto failed :-(\n");
-		res = -1;
-	}
-	check_goto_on_transfer(transferer);
-	return res;
-}
-#endif
-
-#if 0
-/*!
  * \brief make channels compatible
  * \param c
  * \param newchan
@@ -2913,294 +2732,6 @@
 	return ast_get_builtin_feature(chan, feature_name, buf, len);
 }
 
-#if 0
-/*!
- * \brief exec an app by feature
- * \param chan,peer,config,code,sense,data
- *
- * Find a feature, determine which channel activated
- * \retval AST_FEATURE_RETURN_NO_HANGUP_PEER
- * \retval -1 error.
- * \retval -2 when an application cannot be found.
- */
-static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
-{
-	struct ast_app *app;
-	struct ast_call_feature *feature = data;
-	struct ast_channel *work, *idle;
-	int res;
-
-	if (!feature) { /* shouldn't ever happen! */
-		ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
-		return -1;
-	}
-
-	if (sense == FEATURE_SENSE_CHAN) {
-		if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
-			return AST_FEATURE_RETURN_KEEPTRYING;
-		if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
-			work = chan;
-			idle = peer;
-		} else {
-			work = peer;
-			idle = chan;
-		}
-	} else {
-		if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
-			return AST_FEATURE_RETURN_KEEPTRYING;
-		if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
-			work = peer;
-			idle = chan;
-		} else {
-			work = chan;
-			idle = peer;
-		}
-	}
-
-	if (!(app = pbx_findapp(feature->app))) {
-		ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
-		return -2;
-	}
-
-	ast_autoservice_start(idle);
-	ast_autoservice_ignore(idle, AST_FRAME_DTMF_END);
-
-	pbx_builtin_setvar_helper(work, "DYNAMIC_PEERNAME", ast_channel_name(idle));
-	pbx_builtin_setvar_helper(idle, "DYNAMIC_PEERNAME", ast_channel_name(work));
-	pbx_builtin_setvar_helper(work, "DYNAMIC_FEATURENAME", feature->sname);
-	pbx_builtin_setvar_helper(idle, "DYNAMIC_FEATURENAME", feature->sname);
-
-	if (!ast_strlen_zero(feature->moh_class))
-		ast_moh_start(idle, feature->moh_class, NULL);
-
-	res = pbx_exec(work, app, feature->app_args);
-
-	if (!ast_strlen_zero(feature->moh_class))
-		ast_moh_stop(idle);
-
-	ast_autoservice_stop(idle);
-
-	if (res) {
-		return AST_FEATURE_RETURN_SUCCESSBREAK;
-	}
-	return AST_FEATURE_RETURN_SUCCESS;	/*! \todo XXX should probably return res */
-}
-#endif
-
-#if 0
-/*!
- * \brief Helper function for feature_interpret and ast_feature_detect
- * \param chan,peer,config,code,sense,dynamic_features_buf,features,operation,feature
- *
- * Lock features list, browse for code, unlock list
- * If a feature is found and the operation variable is set, that feature's
- * operation is executed.  The first feature found is copied to the feature parameter.
- * \retval res on success.
- * \retval -1 on failure.
- */
-static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
-	struct ast_bridge_config *config, const char *code, int sense, const struct ast_str *dynamic_features_buf,
-	struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
-{
-	int x;
-	struct feature_group *fg = NULL;
-	struct feature_group_exten *fge;
-	struct ast_call_feature *tmpfeature;
-	char *tmp, *tok;
-	int res = AST_FEATURE_RETURN_PASSDIGITS;
-	int feature_detected = 0;
-
-	if (!(peer && chan && config) && operation == FEATURE_INTERPRET_DO) {
-		return -1; /* can not run feature operation */
-	}
-
-	ast_rdlock_call_features();
-	for (x = 0; x < FEATURES_COUNT; x++) {
-		char feature_exten[FEATURE_MAX_LEN] = "";
-
-		if (!ast_test_flag(features, builtin_features[x].feature_mask)) {
-			continue;
-		}
-
-		if (builtin_feature_get_exten(chan, builtin_features[x].sname, feature_exten, sizeof(feature_exten))) {
-			continue;
-		}
-
-		/* Feature is up for consideration */
-
-		if (!strcmp(feature_exten, code)) {
-			ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, feature_exten);
-			if (operation == FEATURE_INTERPRET_CHECK) {
-				res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
-			} else if (operation == FEATURE_INTERPRET_DO) {
-				res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
-				ast_test_suite_event_notify("FEATURE_DETECTION",
-						"Result: success\r\n"
-						"Feature: %s",
-						builtin_features[x].sname);
-			}
-			if (feature) {
-				memcpy(feature, &builtin_features[x], sizeof(*feature));
-			}
-			feature_detected = 1;
-			break;
-		} else if (!strncmp(feature_exten, code, strlen(code))) {
-			if (res == AST_FEATURE_RETURN_PASSDIGITS) {
-				res = AST_FEATURE_RETURN_STOREDIGITS;
-			}
-		}
-	}
-
-	if (operation == FEATURE_INTERPRET_CHECK && x == FEATURES_COUNT) {
-		ast_test_suite_event_notify("FEATURE_DETECTION",
-				"Result: fail");
-	}
-
-	ast_unlock_call_features();
-
-	if (!dynamic_features_buf || !ast_str_strlen(dynamic_features_buf) || feature_detected) {
-		return res;
-	}
-
-	tmp = ast_str_buffer(dynamic_features_buf);
-
-	while ((tok = strsep(&tmp, "#"))) {
-		AST_RWLIST_RDLOCK(&feature_groups);
-		fg = find_group(tok);
-		if (fg) {
-			AST_LIST_TRAVERSE(&fg->features, fge, entry) {
-				if (!strcmp(fge->exten, code)) {
-					if (operation) {
-						res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
-					}
-					if (feature) {
-						memcpy(feature, fge->feature, sizeof(*feature));
-					}
-					if (res != AST_FEATURE_RETURN_KEEPTRYING) {
-						AST_RWLIST_UNLOCK(&feature_groups);
-						break;
-					}
-					res = AST_FEATURE_RETURN_PASSDIGITS;
-				} else if (!strncmp(fge->exten, code, strlen(code))) {
-					res = AST_FEATURE_RETURN_STOREDIGITS;
-				}
-			}
-			if (fge) {
-				break;
-			}
-		}
-		AST_RWLIST_UNLOCK(&feature_groups);
-
-		ast_rdlock_call_features();
-
-		if (!(tmpfeature = find_dynamic_feature(tok))) {
-			ast_unlock_call_features();
-			continue;
-		}
-
-		/* Feature is up for consideration */
-		if (!strcmp(tmpfeature->exten, code)) {
-			ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
-			if (operation == FEATURE_INTERPRET_CHECK) {
-				res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
-			} else if (operation == FEATURE_INTERPRET_DO) {
-				res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
-			}
-			if (feature) {
-				memcpy(feature, tmpfeature, sizeof(*feature));
-			}
-			if (res != AST_FEATURE_RETURN_KEEPTRYING) {
-				ast_unlock_call_features();
-				break;
-			}
-			res = AST_FEATURE_RETURN_PASSDIGITS;
-		} else if (!strncmp(tmpfeature->exten, code, strlen(code)))
-			res = AST_FEATURE_RETURN_STOREDIGITS;
-
-		ast_unlock_call_features();
-	}
-
-	return res;
-}
-#endif
-
-#if 0//BUGBUG
-/*!
- * \brief Check the dynamic features
- * \param chan,peer,config,code,sense
- *
- * \retval res on success.
- * \retval -1 on failure.
- */
-static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense) {
-
-	struct ast_str *dynamic_features_buf;
-	const char *peer_dynamic_features, *chan_dynamic_features;
-	struct ast_flags features;
-	struct ast_call_feature feature;
-	int res;
-
-	if (sense == FEATURE_SENSE_CHAN) {
-		/* Coverity - This uninit_use should be ignored since this macro initializes the flags */
-		ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
-	}
-	else {
-		/* Coverity - This uninit_use should be ignored since this macro initializes the flags */
-		ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
-	}
-
-	ast_channel_lock(peer);
-	peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
-	ast_channel_unlock(peer);
-
-	ast_channel_lock(chan);
-	chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
-	ast_channel_unlock(chan);
-
-	if (!(dynamic_features_buf = ast_str_create(128))) {
-		return AST_FEATURE_RETURN_PASSDIGITS;
-	}
-
-	ast_str_set(&dynamic_features_buf, 0, "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
-
-	ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", ast_channel_name(chan), ast_channel_name(peer), code, sense, features.flags, ast_str_buffer(dynamic_features_buf));
-
-	res = feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, FEATURE_INTERPRET_DO, &feature);
-
-	ast_free(dynamic_features_buf);
-
-	return res;
-}
-#endif
-
-
-#if 0
-int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) {
-	return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_DETECT, feature);
-}
-#endif
-
-#if 0//BUGBUG
-/*! \brief Check if a feature exists */
-static int feature_check(struct ast_channel *chan, struct ast_flags *features, char *code) {
-	struct ast_str *chan_dynamic_features;
-	int res;
-
-	if (!(chan_dynamic_features = ast_str_create(128))) {
-		return AST_FEATURE_RETURN_PASSDIGITS;
-	}
-	ast_channel_lock(chan);
-	ast_str_set(&chan_dynamic_features, 0, "%s", S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
-	ast_channel_unlock(chan);
-
-	res = feature_interpret_helper(chan, NULL, NULL, code, 0, chan_dynamic_features, features, FEATURE_INTERPRET_CHECK, NULL);
-
-	ast_free(chan_dynamic_features);
-
-	return res;
-}
-#endif
-
 static void set_config_flags(struct ast_channel *chan, struct ast_bridge_config *config)
 {
 /* BUGBUG there is code that checks AST_BRIDGE_IGNORE_SIGS but no code to set it. */
@@ -3225,7 +2756,7 @@
 		if (!applicationmap) {
 			return;
 		}
-		
+
 		/* If an applicationmap exists for this channel at all, then the channel needs the DTMF flag set */
 		ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
 	}
@@ -5275,20 +4806,25 @@
 {
 	struct ast_channel *target;/*!< Potential pickup target */
 	int res = -1;
+	RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
+	const char *pickup_sound;
+	const char *fail_sound;
 
 	ast_debug(1, "pickup attempt by %s\n", ast_channel_name(chan));
+	ast_channel_lock(chan);
+	pickup_sound = ast_strdupa(pickup_cfg->pickupsound);
+	fail_sound = ast_strdupa(pickup_cfg->pickupfailsound);
+	ast_channel_unlock(chan);
 
 	/* The found channel is already locked. */
 	target = ast_pickup_find_by_group(chan);
 	if (target) {
-		RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, ast_get_chan_features_pickup_config(target), ao2_cleanup);
-		const char *pickup_sound = ast_strdupa(pickup_cfg->pickupsound);
 		ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", ast_channel_name(target), ast_channel_name(chan));
 
 		res = ast_do_pickup(chan, target);
 		ast_channel_unlock(target);
 		if (!res) {
-			if (!ast_strlen_zero(pickup_cfg->pickupsound)) {
+			if (!ast_strlen_zero(pickup_sound)) {
 				pbx_builtin_setvar_helper(target, "BRIDGE_PLAY_SOUND", pickup_sound);
 			}
 		} else {
@@ -5298,14 +4834,6 @@
 	}
 
 	if (res < 0) {
-		RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
-		const char *fail_sound;
-
-		ast_channel_lock(chan);
-		pickup_cfg = ast_get_chan_features_pickup_config(chan);
-		fail_sound = ast_strdupa(pickup_cfg->pickupfailsound);
-		ast_channel_unlock(chan);
-
 		ast_debug(1, "No call pickup possible... for %s\n", ast_channel_name(chan));
 		if (!ast_strlen_zero(fail_sound)) {
 			ast_answer(chan);
@@ -5744,7 +5272,6 @@
 	return 0;
 }
 
-#if 0
 #if defined(TEST_FRAMEWORK)
 /*!
  * \internal
@@ -6221,11 +5748,12 @@
 	return res ? AST_TEST_FAIL : AST_TEST_PASS;
 }
 #endif	/* defined(TEST_FRAMEWORK) */
-#endif
 
 /*! \internal \brief Clean up resources on Asterisk shutdown */
 static void features_shutdown(void)
 {
+	ast_features_config_shutdown();
+
 	ast_cli_unregister_multiple(cli_features, ARRAY_LEN(cli_features));
 	ast_devstate_prov_del("Park");
 	ast_manager_unregister("Bridge");
@@ -6255,20 +5783,24 @@
 	}
 	ast_cli_register_multiple(cli_features, ARRAY_LEN(cli_features));
 	if (ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL)) {
+		ast_features_config_shutdown();
+		ast_cli_unregister_multiple(cli_features, ARRAY_LEN(cli_features));
 		return -1;
 	}
-	ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
-	if (!res) {
-		ast_manager_register_xml_core("Park", EVENT_FLAG_CALL, manager_park);
-		ast_manager_register_xml_core("Bridge", EVENT_FLAG_CALL, action_bridge);
-	}
+	res |= ast_register_application2(app_bridge, bridge_exec, NULL, NULL, NULL);
+	res |= ast_manager_register_xml_core("Park", EVENT_FLAG_CALL, manager_park);
+	res |= ast_manager_register_xml_core("Bridge", EVENT_FLAG_CALL, action_bridge);
 
 	res |= ast_devstate_prov_add("Park", metermaidstate);
 #if defined(TEST_FRAMEWORK)
 	res |= AST_TEST_REGISTER(features_test);
 #endif	/* defined(TEST_FRAMEWORK) */
 
-	ast_register_atexit(features_shutdown);
+	if (res) {
+		features_shutdown();
+	} else {
+		ast_register_atexit(features_shutdown);
+	}
 
 	return res;
 }

Modified: team/mmichelson/features_config/main/features_config.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/main/features_config.c?view=diff&rev=390384&r1=390383&r2=390384
==============================================================================
--- team/mmichelson/features_config/main/features_config.c (original)
+++ team/mmichelson/features_config/main/features_config.c Mon Jun  3 15:04:26 2013
@@ -48,7 +48,7 @@
 					<enum name="atxfercomplete"><para>Digits to dial to complete an attended transfer</para></enum>
 					<enum name="atxferthreeway"><para>Digits to dial to change an attended transfer into a three-way call</para></enum>
 					<enum name="pickupexten"><para>Digits used for picking up ringing calls</para></enum>
-					<enum name="pickupsound"><para>Sound to play to a caller when a call is picked up</para></enum>
+					<enum name="pickupsound"><para>Sound to play to picker when a call is picked up</para></enum>
 					<enum name="pickupfailsound"><para>Sound to play to picker when a call cannot be picked up</para></enum>
 				</enumlist>
 			</parameter>
@@ -179,41 +179,22 @@
 	ao2_cleanup(item->appmap_item);
 }
 
-static int group_item_hash(const void *obj, int flags)
-{
-	const struct featuregroup_item *item;
-	const char *key;
-
-	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
-	case OBJ_KEY:
-		key = obj;
-		return ast_str_case_hash(key);
-	case OBJ_PARTIAL_KEY:
-		ast_assert(0);
-		return 0;
-	case OBJ_POINTER:
-	default:
-		item = obj;
-		return ast_str_case_hash(item->appmap_item_name);
-	}
-}
-
-static int group_item_cmp(void *obj, void *arg, int flags)
-{
-	struct featuregroup_item *item1 = obj;
-	struct featuregroup_item *item2;
+static int group_item_sort(const void *obj, const void *arg, int flags)
+{
+	const struct featuregroup_item *item1 = obj;
+	const struct featuregroup_item *item2;
 	const char *key2;
 
 	switch(flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
 	case OBJ_KEY:
 		key2 = arg;
-		return strcasecmp(item1->appmap_item_name, key2) ? 0 : CMP_MATCH;
+		return strcasecmp(item1->appmap_item_name, key2);
 	case OBJ_PARTIAL_KEY:
 		key2 = arg;
-		return strncasecmp(item1->appmap_item_name, key2, strlen(key2)) ? 0 : CMP_MATCH;
+		return strncasecmp(item1->appmap_item_name, key2, strlen(key2));
 	case OBJ_POINTER:
 		item2 = arg;
-		return strcasecmp(item1->appmap_item_name, item2->appmap_item_name) ? 0 : CMP_MATCH;
+		return strcasecmp(item1->appmap_item_name, item2->appmap_item_name);
 	default:
 		return CMP_STOP;
 	}
@@ -297,8 +278,8 @@
 		return NULL;
 	}
 
-	group->items = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 5,
-			group_item_hash, group_item_cmp);
+	group->items = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
+			AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, group_item_sort, NULL);
 	if (!group->items) {
 		ao2_cleanup(group);
 		return NULL;
@@ -342,18 +323,18 @@
 	.type = ACO_ITEM,
 	.name = "featuregroup",
 	.category_match = ACO_BLACKLIST,
-	.category = "^(general|featuremap|applicationmap)$",
+	.category = "^(general|featuremap|applicationmap|parkinglot_.*)$",
 	.item_offset = offsetof(struct features_config, featuregroups),
 	.item_alloc = featuregroup_alloc,
 	.item_find = featuregroup_find,
 };
 
-struct aco_type *global_options[] = ACO_TYPES(&global_option);
-struct aco_type *featuremap_options[] = ACO_TYPES(&featuremap_option);
-struct aco_type *applicationmap_options[] = ACO_TYPES(&applicationmap_option);
-struct aco_type *featuregroup_options[] = ACO_TYPES(&featuregroup_option);
-
-struct aco_file features_conf = {
+static struct aco_type *global_options[] = ACO_TYPES(&global_option);
+static struct aco_type *featuremap_options[] = ACO_TYPES(&featuremap_option);
+static struct aco_type *applicationmap_options[] = ACO_TYPES(&applicationmap_option);
+static struct aco_type *featuregroup_options[] = ACO_TYPES(&featuregroup_option);
+
+static struct aco_file features_conf = {
 	.filename = "features.conf",
 	.types = ACO_TYPES(&global_option, &featuremap_option, &applicationmap_option, &featuregroup_option),
 };
@@ -367,6 +348,7 @@
 	ao2_cleanup(cfg->global);
 	ao2_cleanup(cfg->featuremap);
 	ao2_cleanup(cfg->applicationmap);

[... 198 lines stripped ...]



More information about the svn-commits mailing list