[asterisk-commits] rmudgett: branch rmudgett/parking r330994 - /team/rmudgett/parking/main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Aug 5 15:31:31 CDT 2011


Author: rmudgett
Date: Fri Aug  5 15:31:27 2011
New Revision: 330994

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=330994
Log:
* Extracted create_dynamic_parkinglot() from park_space_reserve() so
dynamic parking lots can be created again by DTMF transfer and the Park
application after adding the parking_lot_name option to the Park
application.

* Added PARKINGDYNEXTEN channel variable to allow dynamic parking lots to
specify the parking lot access extension.

Modified:
    team/rmudgett/parking/main/features.c

Modified: team/rmudgett/parking/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/main/features.c?view=diff&rev=330994&r1=330993&r2=330994
==============================================================================
--- team/rmudgett/parking/main/features.c (original)
+++ team/rmudgett/parking/main/features.c Fri Aug  5 15:31:27 2011
@@ -286,14 +286,20 @@
 			registered internally and does not need to be explicitly added
 			into the dialplan, although you should include the parking lot
 			context.</para>
-			<para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
-			parking context, Park() will park the call on that extension, unless
-			it already exists. In that case, execution will continue at the next priority.</para>
-			<para>If you set the <variable>PARKINGDYNAMIC</variable> variable, this parkinglot from
-			<literal>features.conf</literal> will be used as a template for the newly created dynamic lot.</para>
-			<para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable the newly created dynamic
+			<para>If you set the <variable>PARKINGEXTEN</variable> variable to a
+			parking space extension in the parking lot, Park() will attempt to park the call
+			on that extension.  If the extension is already is in use then execution
+			will continue at the next priority.</para>
+			<para>If the <literal>parkeddynamic</literal> option is enabled in features.conf
+			the following variables can be used to dynamically create new parking lots.</para>
+			<para>If you set the <variable>PARKINGDYNAMIC</variable> variable and this parking lot
+			exists then it will be used as a template for the newly created dynamic lot.  Otherwise,
+			the default parking lot will be used.</para>
+			<para>If you set the <variable>PARKINGDYNCONTEXT</variable> variable then the newly created dynamic
 			parking lot will use this context.</para>
-			<para>If you set the <variable>PARKINGDYNPOS</variable> variable the newly created dynamic parkinglot
+			<para>If you set the <variable>PARKINGDYNEXTEN</variable> variable then the newly created dynamic
+			parking lot will use this extension to access the parking lot.</para>
+			<para>If you set the <variable>PARKINGDYNPOS</variable> variable then the newly created dynamic parking lot
 			will use those parking postitions.</para>
 		</description>
 		<see-also>
@@ -1021,16 +1027,122 @@
 
 /*!
  * \internal
+ * \brief Create a dynamic parking lot.
+ *
+ * \param name Dynamic parking lot name to create.
+ * \param chan Channel to get dynamic parking lot parameters.
+ *
+ * \retval parkinglot on success.
+ * \retval NULL on error.
+ */
+static struct ast_parkinglot *create_dynamic_parkinglot(const char *name, struct ast_channel *chan)
+{
+	const char *dyn_context;
+	const char *dyn_exten;
+	const char *dyn_range;
+	const char *template_name;
+	struct ast_parkinglot *template_parkinglot = NULL;
+	struct ast_parkinglot *parkinglot;
+	int dyn_start;
+	int dyn_end;
+
+	ast_channel_lock(chan);
+	template_name = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
+	dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
+	dyn_exten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNEXTEN"), ""));
+	dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
+	ast_channel_unlock(chan);
+
+	if (!ast_strlen_zero(template_name)) {
+		template_parkinglot = find_parkinglot(template_name);
+		if (!template_parkinglot) {
+			ast_debug(1, "PARKINGDYNAMIC lot %s does not exist.\n",
+				template_name);
+		} else if (template_parkinglot->cfg.is_invalid) {
+			ast_debug(1, "PARKINGDYNAMIC lot %s has invalid config.\n",
+				template_name);
+			parkinglot_unref(template_parkinglot);
+			template_parkinglot = NULL;
+		}
+	}
+	if (!template_parkinglot) {
+		template_parkinglot = parkinglot_addref(default_parkinglot);
+		ast_debug(1, "Using default parking lot for template\n");
+	}
+
+	parkinglot = copy_parkinglot(name, template_parkinglot);
+	if (!parkinglot) {
+		ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
+	} else {
+		/* Configure the dynamic parking lot. */
+		if (!ast_strlen_zero(dyn_context)) {
+			ast_copy_string(parkinglot->cfg.parking_con, dyn_context,
+				sizeof(parkinglot->cfg.parking_con));
+		}
+		if (!ast_strlen_zero(dyn_exten)) {
+			ast_copy_string(parkinglot->cfg.parking_con, dyn_exten,
+				sizeof(parkinglot->cfg.parkext));
+		}
+		if (!ast_strlen_zero(dyn_range)) {
+			if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
+				ast_log(LOG_WARNING,
+					"Format for parking positions is a-b, where a and b are numbers\n");
+			} else if (dyn_end < dyn_start || dyn_start <= 0 || dyn_end <= 0) {
+				ast_log(LOG_WARNING,
+					"Format for parking positions is a-b, where a <= b\n");
+			} else {
+				parkinglot->cfg.parking_start = dyn_start;
+				parkinglot->cfg.parking_stop = dyn_end;
+			}
+		}
+
+		/*
+		 * Sanity check for dynamic parking lot configuration.
+		 *
+		 * XXX It may be desirable to instead check if the dynamic
+		 * parking lot overlaps any existing lots like what is done for
+		 * a reload.
+		 */
+		if (!strcmp(parkinglot->cfg.parking_con, template_parkinglot->cfg.parking_con)) {
+			if (!strcmp(parkinglot->cfg.parkext, template_parkinglot->cfg.parkext)) {
+				ast_log(LOG_WARNING,
+					"Parking lot '%s' conflicts with template parking lot '%s'!\n"
+					"Change either PARKINGDYNCONTEXT or PARKINGDYNEXTEN.\n",
+					parkinglot->name, template_parkinglot->name);
+			}
+			if ((template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_start
+					&& parkinglot->cfg.parking_start <= template_parkinglot->cfg.parking_stop)
+				|| (template_parkinglot->cfg.parking_start <= parkinglot->cfg.parking_stop
+					&& parkinglot->cfg.parking_stop <= template_parkinglot->cfg.parking_stop)
+				|| (parkinglot->cfg.parking_start < template_parkinglot->cfg.parking_start
+					&& template_parkinglot->cfg.parking_stop < parkinglot->cfg.parking_stop)) {
+				ast_log(LOG_WARNING,
+					"Parking lot '%s' parking spaces overlap template parking lot '%s'!\n"
+					"Change PARKINGDYNPOS.\n",
+					parkinglot->name, template_parkinglot->name);
+			}
+		}
+
+		parkinglot_activate(parkinglot);
+		ao2_link(parkinglots, parkinglot);
+	}
+	parkinglot_unref(template_parkinglot);
+
+	return parkinglot;
+}
+
+/*!
+ * \internal
  * \brief Reserve a parking space in a parking lot for a call being parked.
  *
- * \param chan Channel being parked.
- * \param peer Channel parking the call.
+ * \param park_me Channel being parked.
+ * \param parker Channel parking the call.
  * \param args Optional additional parking options when parking a call.
  *
  * \return Parked call descriptor or NULL if failed.
  * \note The parking lot list is locked if successful.
  */
-static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
+static struct parkeduser *park_space_reserve(struct ast_channel *park_me, struct ast_channel *parker, struct ast_park_call_args *args)
 {
 	struct parkeduser *pu;
 	int i;
@@ -1044,10 +1156,10 @@
 		parkinglot = parkinglot_addref(args->parkinglot);
 		parkinglotname = parkinglot->name;
 	} else {
-		if (peer) {
-			parkinglotname = findparkinglotname(peer);
-		} else { /* peer was NULL, check chan (ParkAndAnnounce / res_agi) */
-			parkinglotname = findparkinglotname(chan);
+		if (parker) {
+			parkinglotname = findparkinglotname(parker);
+		} else { /* parker was NULL, check park_me (ParkAndAnnounce / res_agi) */
+			parkinglotname = findparkinglotname(park_me);
 		}
 		if (!ast_strlen_zero(parkinglotname)) {
 			parkinglot = find_parkinglot(parkinglotname);
@@ -1060,70 +1172,11 @@
 
 	/* Dynamically create parkinglot */
 	if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) {
-		const char *dyn_context;
-		const char *dyn_range;
-		const char *parkinglotname_copy;
-		struct ast_parkinglot *parkinglot_copy = NULL;
-		int dyn_start;
-		int dyn_end;
-
-		/* XXX Why are we getting dynamic parkinglot information from chan and not peer? */
-		ast_channel_lock(chan);
-		parkinglotname_copy = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"), ""));
-		dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"), ""));
-		dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"), ""));
-		ast_channel_unlock(chan);
-
-		if (!ast_strlen_zero(parkinglotname_copy)) {
-			parkinglot_copy = find_parkinglot(parkinglotname_copy);
-			if (!parkinglot_copy) {
-				ast_debug(1, "PARKINGDYNAMIC lot %s does not exist.\n",
-					parkinglotname_copy);
-			} else if (parkinglot_copy->cfg.is_invalid) {
-				ast_debug(1, "PARKINGDYNAMIC lot %s has invalid config.\n",
-					parkinglotname_copy);
-				parkinglot_unref(parkinglot_copy);
-				parkinglot_copy = NULL;
-			}
-		}
-		if (!parkinglot_copy) {
-			parkinglot_copy = parkinglot_addref(default_parkinglot);
-			ast_debug(1, "Using default parking lot for copy\n");
-		}
-		parkinglot = copy_parkinglot(parkinglotname, parkinglot_copy);
-
-/* BUGBUG we should check that the dynamic parking lot does not use the same context and parkext as the template lot. */
-/* If this is the case it will make the template lot difficult to park new calls in using the standard access ramp. */
-		/* unref our temporary copy */
-		parkinglot_unref(parkinglot_copy);
-		parkinglot_copy = NULL;
-
-		if (!parkinglot) {
-			ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
-		} else {
-			if (!ast_strlen_zero(dyn_context)) {
-				ast_copy_string(parkinglot->cfg.parking_con, dyn_context,
-					sizeof(parkinglot->cfg.parking_con));
-			}
-			if (!ast_strlen_zero(dyn_range)) {
-				if (sscanf(dyn_range, "%30d-%30d", &dyn_start, &dyn_end) != 2) {
-					ast_log(LOG_WARNING,
-						"Format for parking positions is a-b, where a and b are numbers\n");
-				} else if (dyn_end < dyn_start || dyn_start <= 0 || dyn_end <= 0) {
-					ast_log(LOG_WARNING,
-						"Format for parking positions is a-b, where a <= b\n");
-				} else {
-					parkinglot->cfg.parking_start = dyn_start;
-					parkinglot->cfg.parking_stop = dyn_end;
-				}
-			}
-			parkinglot_activate(parkinglot);
-			ao2_link(parkinglots, parkinglot);
-		}
+		parkinglot = create_dynamic_parkinglot(parkinglotname, park_me);
 	}
 
 	if (!parkinglot) {
-		ast_log(LOG_WARNING, "Parking lot not available to park %s.\n", chan->name);
+		ast_log(LOG_WARNING, "Parking lot not available to park %s.\n", park_me->name);
 		return NULL;
 	}
 
@@ -1145,7 +1198,7 @@
 	AST_LIST_LOCK(&parkinglot->parkings);
 
 	/* Check for channel variable PARKINGEXTEN */
-	parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"), ""));
+	parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(park_me, "PARKINGEXTEN"), ""));
 	if (!ast_strlen_zero(parkingexten)) {
 		/*!
 		 * \note The API forces us to specify a numeric parking slot, even
@@ -1443,8 +1496,8 @@
 }
 
 /*!
- * \param rchan is the transferee
- * \param peer is the transferer
+ * \param rchan the real channel to be parked
+ * \param peer the channel to have the parking read to.
  */
 static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement, struct ast_park_call_args *args)
 {
@@ -1573,6 +1626,10 @@
 		args.parkinglot = parkinglot_addref(default_parkinglot);
 	} else {
 		args.parkinglot = find_parkinglot(pl_name);
+		if (!args.parkinglot && parkeddynamic) {
+			args.parkinglot = create_dynamic_parkinglot(pl_name, park_me);
+		}
+
 	}
 	if (args.parkinglot) {
 		res = masq_park_call_announce(park_me, parker, &args);
@@ -4660,6 +4717,9 @@
 		args.parkinglot = parkinglot_addref(default_parkinglot);
 	} else {
 		args.parkinglot = find_parkinglot(pl_name);
+		if (!args.parkinglot && parkeddynamic) {
+			args.parkinglot = create_dynamic_parkinglot(pl_name, chan);
+		}
 	}
 	if (args.parkinglot) {
 		res = masq_park_call_announce(chan, chan, &args);




More information about the asterisk-commits mailing list