[asterisk-commits] jrose: branch jrose/bridge_projects r383612 - in /team/jrose/bridge_projects:...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Mar 22 14:28:53 CDT 2013


Author: jrose
Date: Fri Mar 22 14:28:49 2013
New Revision: 383612

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383612
Log:
Getting ready for stasis changes

Modified:
    team/jrose/bridge_projects/include/asterisk/config_options.h
    team/jrose/bridge_projects/include/asterisk/parking.h
    team/jrose/bridge_projects/res/parking/parking_applications.c
    team/jrose/bridge_projects/res/parking/parking_controller.c
    team/jrose/bridge_projects/res/parking/parking_ui.c
    team/jrose/bridge_projects/res/parking/res_parking.h
    team/jrose/bridge_projects/res/res_parking.c

Modified: team/jrose/bridge_projects/include/asterisk/config_options.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/config_options.h?view=diff&rev=383612&r1=383611&r2=383612
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/config_options.h (original)
+++ team/jrose/bridge_projects/include/asterisk/config_options.h Fri Mar 22 14:28:49 2013
@@ -575,7 +575,10 @@
  */
 int aco_option_register_deprecated(struct aco_info *info, const char *name, struct aco_type **types, const char *aliased_to);
 
-/*! \brief Read the flags of a config option - useful when using a custom callback for a config option
+/*!
+ * \brief Read the flags of a config option - useful when using a custom callback for a config option
+ * \since 12
+ *
  * \param option Pointer to the aco_option struct
  *
  * \retval value of the flags on the config option

Modified: team/jrose/bridge_projects/include/asterisk/parking.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/parking.h?view=diff&rev=383612&r1=383611&r2=383612
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/parking.h (original)
+++ team/jrose/bridge_projects/include/asterisk/parking.h Fri Mar 22 14:28:49 2013
@@ -25,7 +25,10 @@
 
 #include "asterisk/stringfields.h"
 
-/*! \brief Defines the type of parked call message */
+/*!
+ * \brief Defines the type of parked call message
+ * \since 12
+ */
 enum ast_parked_call_event_type {
 	PARKED_CALL = 0,
 	PARKED_CALL_TIMEOUT,
@@ -69,7 +72,7 @@
  * \retval NULL if the payload could not be allocated
  * \retval reference to the payload object
  *
- * \note This reference should be free'd when it is no longer in use.
+ * \note ao2_cleanup this reference once it is no longer in use.
  */
 struct ast_parked_call_payload *ast_parked_call_payload_create(void);
 
@@ -80,7 +83,7 @@
  * \retval NULL if the payload could not be allocated
  * \retval reference to the payload object
  *
- * \note This reference should be free'd when it is no longer in use.
+ * \note ao2_cleanup this reference once it is no longer in use.
  */
 struct ast_parking_lot_payload *ast_parking_lot_payload_create(void);
 

Modified: team/jrose/bridge_projects/res/parking/parking_applications.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_applications.c?view=diff&rev=383612&r1=383611&r2=383612
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_applications.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_applications.c Fri Mar 22 14:28:49 2013
@@ -136,9 +136,9 @@
 	return 0;
 }
 
-static int park_exec(struct ast_channel *chan, const char *data)
+int park_app_exec(struct ast_channel *chan, const char *data)
 {
-	RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
+	RAII_VAR(struct parking_lot_state *, lot, NULL, ao2_cleanup);
 	RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
 
@@ -173,7 +173,7 @@
 	if (ast_strlen_zero(args.lot_name)) {
 		lot = channel_find_parkinglot(chan);
 	} else {
-		lot = parking_lot_get(args.lot_name);
+		lot = parking_lot_find_by_name(args.lot_name);
 	}
 
 	if (!lot) {
@@ -239,8 +239,3 @@
 
 	return ast_check_hangup_locked(chan) ? -1 : 0;
 }
-
-void *parking_get_park_app_cb()
-{
-	return park_exec;
-}

Modified: team/jrose/bridge_projects/res/parking/parking_controller.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_controller.c?view=diff&rev=383612&r1=383611&r2=383612
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_controller.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_controller.c Fri Mar 22 14:28:49 2013
@@ -66,7 +66,7 @@
 		snprintf(timeout_text, sizeof(timeout_text), "%ld", pu->start.tv_sec + (long) pu->time_limit - now.tv_sec);
 	}
 
-	ast_string_field_set(payload, parkinglot, pu->lot->name);
+	ast_string_field_set(payload, parkinglot, pu->lot_state->name);
 	ast_string_field_build(payload, parkingspace, "%d", pu->parking_space);
 	ast_string_field_set(payload, timeout, timeout_text);
 	ast_string_field_build(payload, duration, "%ld", now.tv_sec - pu->start.tv_sec);
@@ -81,7 +81,7 @@
 	}
 }
 
-void publish_parking_lot(struct parking_lot *lot)
+void publish_parking_lot_state(struct parking_lot_state *lot)
 {
 	RAII_VAR(struct ast_parking_lot_payload *, payload, NULL, ao2_cleanup);
 	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
@@ -104,13 +104,13 @@
 	stasis_publish(ast_parking_lot_topic(), msg);
 }
 
-struct ast_bridge *get_parkinglot_bridge(struct parking_lot *lot)
+struct ast_bridge *get_parkinglot_bridge(struct parking_lot_state *state)
 {
 	struct ast_bridge *lot_bridge;
 
-	if (lot->parking_bridge) {
-		ao2_ref(lot->parking_bridge, +1);
-		return lot->parking_bridge;
+	if (state->parking_bridge) {
+		ao2_ref(state->parking_bridge, +1);
+		return state->parking_bridge;
 	}
 
 	/* XXX Richard is going to change some things here. Name will be an argument */
@@ -120,21 +120,21 @@
 	}
 
 	/* The parking lot needs a reference to the bridge as well. */
-	lot->parking_bridge = lot_bridge;
-	ao2_ref(lot->parking_bridge, +1);
+	state->parking_bridge = lot_bridge;
+	ao2_ref(state->parking_bridge, +1);
 
 	return lot_bridge;
 }
 
-void parking_channel_set_roles(struct ast_channel *chan, struct parking_lot *lot, int force_ringing)
+void parking_channel_set_roles(struct ast_channel *chan, struct parking_lot_state *lot_state, int force_ringing)
 {
 	ast_channel_add_bridge_role(chan, "holding_participant");
 	if (force_ringing) {
 		ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "ringing");
 	} else {
 		ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "musiconhold");
-		if (!ast_strlen_zero(lot->mohclass)) {
-			ast_channel_set_bridge_role_option(chan, "holding_participant", "moh_class", lot->mohclass);
+		if (!ast_strlen_zero(lot_state->mohclass)) {
+			ast_channel_set_bridge_role_option(chan, "holding_participant", "moh_class", lot_state->mohclass);
 		}
 	}
 }
@@ -182,9 +182,10 @@
 
 int unpark_parked_user(struct parked_user *pu)
 {
-	if (pu->lot) {
-		ao2_unlink(pu->lot->parked_user_list, pu);
-		pu->lot = NULL;
+	if (pu->lot_state) {
+		ao2_unlink(pu->lot_state->parked_user_list, pu);
+		parking_lot_remove_if_unused(pu->lot_state);
+		pu->lot_state = NULL;
 		return 0;
 	}
 
@@ -198,7 +199,7 @@
 	if (override_time >= 0) {
 		time_limit = override_time * 1000;
 	} else {
-		time_limit = user->lot ? user->lot->parkingtime * 1000 : 0;
+		time_limit = user->lot_state ? user->lot_state->parkingtime * 1000 : 0;
 	}
 
 	if (!time_limit) {
@@ -215,15 +216,23 @@
 	}
 }
 
-int parking_lot_get_space(struct parking_lot *lot, int target_override)
-{
-	int original_target = lot->parkfindnext ? lot->next_space ? lot->next_space : lot->parking_start : lot->parking_start;
+int parking_lot_get_space(struct parking_lot_state *lot, int target_override)
+{
+	int original_target;
 	int current_target;
 	struct ao2_iterator i;
 	struct parked_user *user;
 	int wrap;
 
-	if (target_override != -1 && target_override >= lot->parking_start && target_override <= lot->parking_stop) {
+	if (lot->parkfindnext) {
+		/* Use next_space if the lot has already has next_space set; otherwise use lot start. */
+		original_target = lot->next_space ? lot->next_space : lot->parking_start;
+	} else {
+		/* If not using find next mode, we just start at the start of the parking lot always. */
+		original_target = lot->parking_start;
+	}
+
+	if (target_override >= lot->parking_start && target_override <= lot->parking_stop) {
 		original_target = target_override;
 	}
 
@@ -300,7 +309,7 @@
 	ast_channel_priority_set(chan, priority);
 }
 
-int comeback_goto(struct parked_user *pu, struct parking_lot *lot)
+int comeback_goto(struct parked_user *pu, struct parking_lot_state *lot_state)
 {
 	struct ast_channel *chan = pu->chan;
 	char *peername = ast_strdupa(pu->parker->name);
@@ -308,7 +317,7 @@
 	/* Flatten the peername so that it can be used for performing the timeout PBX operations */
 	flatten_peername(peername);
 
-	if (lot->comebacktoorigin) {
+	if (lot_state->comebacktoorigin) {
 		if (ast_exists_extension(chan, PARK_DIAL_CONTEXT, peername, 1, NULL)) {
 			set_c_e_p(chan, PARK_DIAL_CONTEXT, peername, 1);
 		} else {
@@ -318,19 +327,19 @@
 		}
 	}
 
-	if (ast_exists_extension(chan, lot->comebackcontext, peername, 1, NULL)) {
-		set_c_e_p(chan, lot->comebackcontext, peername, 1);
-	}
-
-	if (ast_exists_extension(chan, lot->comebackcontext, "s", 1, NULL)) {
+	if (ast_exists_extension(chan, lot_state->comebackcontext, peername, 1, NULL)) {
+		set_c_e_p(chan, lot_state->comebackcontext, peername, 1);
+	}
+
+	if (ast_exists_extension(chan, lot_state->comebackcontext, "s", 1, NULL)) {
 		ast_verb(2, "Could not start %s at %s,%s,1. Using 's@%s' instead.\n", ast_channel_name(chan),
-			lot->comebackcontext, peername, lot->comebackcontext);
-		set_c_e_p(chan, lot->comebackcontext, "s", 1);
+			lot_state->comebackcontext, peername, lot_state->comebackcontext);
+		set_c_e_p(chan, lot_state->comebackcontext, "s", 1);
 	}
 
 	ast_verb(2, "Can not start %s at %s,%s,1 and exten 's@%s' does not exist. Using 's at default'\n",
 		ast_channel_name(chan),
-		lot->comebackcontext, peername, lot->comebackcontext);
+		lot_state->comebackcontext, peername, lot_state->comebackcontext);
 	set_c_e_p(chan, "default", "s", 1);
 
 	return 0;
@@ -341,21 +350,26 @@
 	pu->start = ast_tvnow();
 }
 
-struct parked_user *generate_parked_user(struct parking_lot *lot, struct ast_channel *chan, struct ast_channel *parker, int use_random_space, int time_limit)
+struct parked_user *generate_parked_user(struct parking_lot_state *lot_state, struct ast_channel *chan, struct ast_channel *parker, int use_random_space, int time_limit)
 {
 	struct parked_user *new_parked_user;
 	int preferred_space = -1; /* Initialize to use parking lot defaults */
 	int parking_space;
 	const char *parkingexten;
 
+	if (lot_state->parking_disabled) {
+		ast_log(LOG_NOTICE, "Tried to park in a parking lot that is no longer able to be parked to.\n");
+		return NULL;
+	}
+
 	new_parked_user = ao2_alloc(sizeof(*new_parked_user), destroy_parked_user);
 	if (!new_parked_user) {
 		return NULL;
 	}
 
 	if (use_random_space) {
-		preferred_space = ast_random() % (lot->parking_stop - lot->parking_start + 1);
-		preferred_space += lot->parking_start;
+		preferred_space = ast_random() % (lot_state->parking_stop - lot_state->parking_start + 1);
+		preferred_space += lot_state->parking_start;
 	} else if ((parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"), "")))) {
 		if (!ast_strlen_zero(parkingexten)) {
 			if (sscanf(parkingexten, "%30d", &preferred_space) != 1 || preferred_space <= 0) {
@@ -366,27 +380,28 @@
 		}
 	}
 
-	/* We need to keep the lot locked between parking_lot_get_space and actually placing it in the lot. Or until we decide not to. */
-	ao2_lock(lot);
-
-	parking_space = parking_lot_get_space(lot, preferred_space);
+	/* We need to keep the lot state locked between parking_lot_get_space and actually placing it in the lot. Or until we decide not to. */
+	ao2_lock(lot_state);
+
+	parking_space = parking_lot_get_space(lot_state, preferred_space);
 	if (parking_space == -1) {
-		ast_log(LOG_NOTICE, "Failed to get parking space in lot '%s'. All full.\n", lot->name);
+		ast_log(LOG_NOTICE, "Failed to get parking space in lot '%s'. All full.\n", lot_state->name);
 		ao2_ref(new_parked_user, -1);
-		ao2_unlock(lot);
+		ao2_unlock(lot_state);
 		return NULL;
 	}
-	lot->next_space = ((parking_space + 1) - lot->parking_start) % (lot->parking_stop - lot->parking_start + 1) + lot->parking_start;
+
+	lot_state->next_space = ((parking_space + 1) - lot_state->parking_start) % (lot_state->parking_stop - lot_state->parking_start + 1) + lot_state->parking_start;
 	new_parked_user->chan = chan;
 	new_parked_user->parking_space = parking_space;
-	new_parked_user->lot = lot;
+	new_parked_user->lot_state = lot_state;
 	new_parked_user->start = ast_tvnow();
-	new_parked_user->time_limit = (time_limit >= 0) ? time_limit : lot->parkingtime;
+	new_parked_user->time_limit = (time_limit >= 0) ? time_limit : lot_state->parkingtime;
 	new_parked_user->parker = ast_channel_snapshot_create(parker);
 	if (!new_parked_user->parker) {
 		ast_log(LOG_ERROR, "Allocation error\n");
 		ao2_ref(new_parked_user, -1);
-		ao2_unlock(lot);
+		ao2_unlock(lot_state);
 		return NULL;
 	}
 
@@ -394,8 +409,8 @@
 	publish_parked_call(new_parked_user, PARKED_CALL);
 
 	/* Insert into the parking lot's parked user list. We can unlock the lot now. */
-	ao2_link(lot->parked_user_list, new_parked_user);
-	ao2_unlock(lot);
+	ao2_link(lot_state->parked_user_list, new_parked_user);
+	ao2_unlock(lot_state);
 
 	return new_parked_user;
 }

Modified: team/jrose/bridge_projects/res/parking/parking_ui.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_ui.c?view=diff&rev=383612&r1=383611&r2=383612
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_ui.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_ui.c Fri Mar 22 14:28:49 2013
@@ -65,15 +65,16 @@
 
 static void cli_display_parking_lot(int fd, const char *name)
 {
-	RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
+	RAII_VAR(struct parking_lot_state *, lot, NULL, ao2_cleanup);
 	struct ao2_iterator i;
 	struct parked_user *user;
 	int total = 0;
 
-	lot = parking_lot_get(name);
+	lot = parking_lot_find_by_name(name);
 
 	/* If the parking lot couldn't be found with the search, also abort. */
 	if (!lot) {
+		ast_cli(fd, "Could not find parking lot '%s'\n\n", name);
 		return;
 	}
 
@@ -86,7 +87,7 @@
 	ast_cli(fd, "Comeback Context       :      %s%s\n", lot->comebackcontext, lot->comebacktoorigin ? " (comebacktoorigin=yes, not used)" : "");
 	ast_cli(fd, "Comeback Dial Time     :      %u sec\n", lot->comebackdialtime);
 	ast_cli(fd, "MusicOnHold Class      :      %s\n", lot->mohclass);
-	ast_cli(fd, "Enabled                :      %s\n", lot->disabled ? "no" : "yes");
+	ast_cli(fd, "Enabled                :      %s\n", lot->parking_disabled ? "no" : "yes");
 	ast_cli(fd, "\n");
 	ast_cli(fd, "Parked Calls\n------------\n");
 
@@ -113,7 +114,7 @@
 	struct ao2_iterator *i;
 	void *o;
 
-	i = parking_lot_iterator_create();
+	i = parking_lot_state_iterator_create();
 
 	if (!i) {
 		ast_cli(fd, "Parking Lot configuration is unavailable.\n");
@@ -121,7 +122,7 @@
 	}
 
 	while ((o = ao2_iterator_next(i))) {
-		struct parking_lot *lot = o;
+		struct parking_lot_state *lot = o;
 		ast_cli(fd, "\n");
 		ast_cli(fd, "Parking lot: %s\n", lot->name);
 		ast_cli(fd, "------------\n");
@@ -133,12 +134,12 @@
 		ast_cli(fd, "Comeback Context       :      %s%s\n", lot->comebackcontext, lot->comebacktoorigin ? "(comebacktoorigin=yes, not used)" : "");
 		ast_cli(fd, "Comeback Dial Time     :      %u sec\n", lot->comebackdialtime);
 		ast_cli(fd, "MusicOnHold Class      :      %s\n", lot->mohclass);
-		ast_cli(fd, "Enabled                :      %s\n", lot->disabled ? "no" : "yes");
+		ast_cli(fd, "Enabled                :      %s\n", lot->parking_disabled ? "no" : "yes");
 		ast_cli(fd, "\n");
 		ao2_ref(o, -1);
 	}
 
-	parking_lot_iterator_destroy(i);
+	parking_lot_state_iterator_destroy(i);
 }
 
 /* \brief Parkinglots command show <name> */
@@ -147,7 +148,7 @@
 	int length;
 	int which;
 	struct ao2_iterator *i;
-	struct parking_lot *lot;
+	struct parking_lot_state *lot;
 	char *match = NULL;
 
 	switch (cmd) {
@@ -160,7 +161,7 @@
 	case CLI_GENERATE:
 		length = strlen(a->word);
 		which = 0;
-		i = parking_lot_iterator_create();
+		i = parking_lot_state_iterator_create();
 		while ((lot = ao2_iterator_next(i))) {
 			if (!strncasecmp(a->word, lot->name, length) && ++which > a->n) {
 				match = ast_strdup(lot->name);
@@ -169,7 +170,7 @@
 			}
 			ao2_ref(lot, -1);
 		}
-		parking_lot_iterator_destroy(i);
+		parking_lot_state_iterator_destroy(i);
 		return match;
 		return NULL;
 	}
@@ -192,13 +193,13 @@
 	const char *id = astman_get_header(m, "ActionID");
 	char id_text[256] = "";
 	struct ao2_iterator *iter;
-	struct parking_lot *curlot;
+	struct parking_lot_state *curlot;
 
 	if (!ast_strlen_zero(id)) {
 		snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
 	}
 
-	iter = parking_lot_iterator_create();
+	iter = parking_lot_state_iterator_create();
 
 	if (!iter) {
 		ast_log(LOG_ERROR, "Failed to create parking lot iterator. Action canceled.\n");
@@ -209,11 +210,11 @@
 	astman_send_ack(s, m, "Parking lots will follow");
 
 	while ((curlot = ao2_iterator_next(iter))) {
-		publish_parking_lot(curlot);
+		publish_parking_lot_state(curlot);
 		ao2_ref(curlot, -1);
 	}
 
-	parking_lot_iterator_destroy(iter);
+	parking_lot_state_iterator_destroy(iter);
 
 	return RESULT_SUCCESS;
 }
@@ -225,13 +226,13 @@
 	char id_text[256] = "";
 	struct ao2_iterator *iter_lots;
 	struct ao2_iterator iter_users;
-	struct parking_lot *curlot;
+	struct parking_lot_state *curlot;
 
 	if (!ast_strlen_zero(id)) {
 		snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
 	}
 
-	iter_lots = parking_lot_iterator_create();
+	iter_lots = parking_lot_state_iterator_create();
 
 	if (!iter_lots) {
 		ast_log(LOG_ERROR, "Failed to create parking lot iterator. Action canceled.\n");
@@ -251,7 +252,7 @@
 		ao2_ref(curlot, -1);
 	}
 
-	parking_lot_iterator_destroy(iter_lots);
+	parking_lot_state_iterator_destroy(iter_lots);
 
 	return RESULT_SUCCESS;
 }
@@ -260,7 +261,7 @@
 	AST_CLI_DEFINE(handle_show_parking_lot_cmd, "Show a parking lot or a list of all parking lots."),
 };
 
-int load_tools(void)
+int load_parking_ui(void)
 {
 	int res;
 
@@ -271,7 +272,7 @@
 	return res ? -1 : 0;
 }
 
-void unload_tools(void)
+void unload_parking_ui(void)
 {
 	ast_cli_unregister_multiple(cli_parking_lot, ARRAY_LEN(cli_parking_lot));
 	ast_manager_unregister("Parkinglots");

Modified: team/jrose/bridge_projects/res/parking/res_parking.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/res_parking.h?view=diff&rev=383612&r1=383611&r2=383612
==============================================================================
--- team/jrose/bridge_projects/res/parking/res_parking.h (original)
+++ team/jrose/bridge_projects/res/parking/res_parking.h Fri Mar 22 14:28:49 2013
@@ -47,36 +47,34 @@
 	OPT_PARKEDRECORDING,
 };
 
-struct parking_lot {
+struct parking_lot_state {
 	int parking_start;
 	int parking_stop;
+	int next_space;
 
 	unsigned int parkingtime;
 	unsigned int comebackdialtime;
-
 	unsigned int parkfindnext;
 	unsigned int parkext_exclusive;
 	unsigned int parkaddhints;
 	unsigned int comebacktoorigin;
-
-	/* These all need to be handled by a special configuration handler */
 	int parkedplay;
 	int parkedcalltransfers;
 	int parkedcallreparking;
 	int parkedcallhangup;
 	int parkedcallrecording;
 
-	/*! Next space should be... */
-	int next_space;
-
-	/*! Was this parking space created dynamically? (break down the parking lot once it empties) */
-	int dynamic;
+	/* When a parking lot becomes unconfigured, this flag is raised to keep new calls from entering */
+	int parking_disabled;
 
 	/*! Which holding bridge the parking lot uses for placing calls */
 	struct ast_bridge *parking_bridge;
 
 	/*! Ordered list of active parkings in this parkinglot */
 	struct ao2_container *parked_user_list;
+
+	/*! Does this parking lot have a configuration that owns it? Used to determine if we should unlink ourselves from the global state list */
+	int has_owner;
 
 	AST_DECLARE_STRING_FIELDS(
 		AST_STRING_FIELD(name);
@@ -86,26 +84,85 @@
 		AST_STRING_FIELD(comebackcontext);
 		AST_STRING_FIELD(courtesytone);
 	);
-
-	/*! Destroy unused parking lot on deletion marker */
-	unsigned int the_mark:1;
-	/*! TRUE if the parking lot is disabled */
-	unsigned int disabled:1;
+};
+
+struct parking_lot_cfg {
+	int parking_start;
+	int parking_stop;
+
+	unsigned int parkingtime;
+	unsigned int comebackdialtime;
+
+	unsigned int parkfindnext;
+	unsigned int parkext_exclusive;
+	unsigned int parkaddhints;
+	unsigned int comebacktoorigin;
+
+	/* These all need to be handled by a special configuration handler */
+	int parkedplay;
+	int parkedcalltransfers;
+	int parkedcallreparking;
+	int parkedcallhangup;
+	int parkedcallrecording;
+
+	/*!
+	 * State of the parkinglot
+	 * Generated on creation of the parking lot
+	 * Unlinked (and destroyed) when the parking lot is destroyed if and only if the parked call list is empty
+	 * If not referenced by a parking lot, this will be destroyed when the last call is unparked
+	 */
+	struct parking_lot_state *state;
+
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(name);
+		AST_STRING_FIELD(mohclass);
+		AST_STRING_FIELD(parkext);
+		AST_STRING_FIELD(parking_con);
+		AST_STRING_FIELD(comebackcontext);
+		AST_STRING_FIELD(courtesytone);
+	);
 };
 
 struct parked_user {
-	struct ast_channel *chan;				/*!< Parked channel */
-	struct ast_channel_snapshot *parker;	/*!< Snapshot of the channel that parked the call at the time of parking */
-	struct timeval start;					/*!< When the call was parked */
-	int parking_space;						/*!< Which parking space is used */
-	char context[AST_MAX_CONTEXT];			/*!< Where to go on parking timeout (context) */
-	char exten[AST_MAX_CONTEXT];			/*!< Where to go on parking timeout (extension) */
-	unsigned int time_limit;				/*!< How long this specific channel may remain in the parking lot before timing out */
-	struct parking_lot *lot;				/*!< Which parking lot the user is parked to */
-	enum park_call_resolution resolution;	/*!< How did the parking session end? */
-};
-
-/*!
+	struct ast_channel *chan;               /*!< Parked channel */
+	struct ast_channel_snapshot *parker;    /*!< Snapshot of the channel that parked the call at the time of parking */
+	struct timeval start;                   /*!< When the call was parked */
+	int parking_space;                      /*!< Which parking space is used */
+	char context[AST_MAX_CONTEXT];          /*!< Where to go on parking timeout (context) */
+	char exten[AST_MAX_CONTEXT];            /*!< Where to go on parking timeout (extension) */
+	unsigned int time_limit;                /*!< How long this specific channel may remain in the parking lot before timing out */
+	struct parking_lot_state *lot_state;    /*!< Which parking lot the user is parked to */
+	enum park_call_resolution resolution;   /*!< How did the parking session end? */
+};
+
+/*!
+ * \since 12
+ * \brief If a parking lot state exists in the state list already, return a reference to it. Otherwise,
+ *        create a parking lot state struct based on a parking lot configuration and return a reference
+ *
+ * \param lot The lot being used as a reference to build the parking lot state from.
+ *
+ * \retval A reference to the new parking lot state
+ * \retval NULL if it couldn't be allocated
+ *
+ * \note The state will need to be unreffed if it ever falls out of scope
+ * \note The state will automatically be added to the state container if needed as part of this process
+ */
+struct parking_lot_state *parking_lot_state_build_or_find(struct parking_lot_cfg *lot);
+
+/*!
+ * \since 12
+ * \brief Remove a parking lot from the usable lists if it is no longer involved in any calls and no configuration currently claims it
+ *
+ * \param lot Which parking lot state is being checked for elimination
+ *
+ * \note This should generally be called when something is happening that could cause a parking lot to die such as a call being unparked or
+ *       a parking lot no longer existing in configurations.
+ */
+void parking_lot_remove_if_unused(struct parking_lot_state *lot);
+
+/*!
+ * \since 12
  * \brief Get a reference to a parking lot's bridge. If it doesn't exist, create it and get a reference.
  *
  * \param lot Which parking lot we need the bridge from. This parking lot must be locked before calling this function.
@@ -115,32 +172,35 @@
  *
  * \note This bridge will need to be unreffed if it ever falls out of scope.
  */
-struct ast_bridge *get_parkinglot_bridge(struct parking_lot *lot);
-
-/*!
+struct ast_bridge *get_parkinglot_bridge(struct parking_lot_state *state);
+
+/*!
+ * \since 12
  * \brief Get an available parking space within a parking lot.
  *
  * \param lot Which parking lot we are getting a space from
  * \param target_override If there is a specific slot we want, provide it here and we'll start from that position
  *
- * retval -1 if No slot can be found
- * retval integer value of parking space selected
+ * \retval -1 if No slot can be found
+ * \retval integer value of parking space selected
  *
  * \note lot should be locked before this is called and unlocked only after a parked_user with the space
  *       returned has been added to the parking lot.
  */
-int parking_lot_get_space(struct parking_lot *lot, int target_override);
-
-/*!
+int parking_lot_get_space(struct parking_lot_state *lot, int target_override);
+
+/*!
+ * \since 12
  * \brief Set necessary bridge roles on a channel that is about to enter a parking lot
  *
  * \param chan Entering channel
- * \param lot The parking lot the channel will be entering
+ * \param lot_state The parking lot state the channel will be entering
  * \param force_ringing Use ringing instead of music on hold
  */
-void parking_channel_set_roles(struct ast_channel *chan, struct parking_lot *lot, int force_ringing);
-
-/*!
+void parking_channel_set_roles(struct ast_channel *chan, struct parking_lot_state *lot_state, int force_ringing);
+
+/*!
+ * \since 12
  * \brief Setup timeout interval feature on an ast_bridge_features for parking
  *
  * \param features The ast_bridge_features we are establishing the interval hook on
@@ -150,49 +210,54 @@
 void parking_set_duration(struct ast_bridge_features *features, struct parked_user *user, int override_time);
 
 /*!
- * \brief Create an iterator which will iterate through all configured parking_lot structs
- *
- * \retval iterator for parking lots if successful
+ * \since 12
+ * \brief Create an iterator which will iterate through all parking_lot_state structs
+ *
+ * \retval iterator for parking lot states if successful
  * \retval NULL if the iterator could not be initialized
  *
  * \note If this succeeds, the iterator should be destroyed using parking_lot_iterator_destroy when it is no longer needed.
  */
-struct ao2_iterator *parking_lot_iterator_create(void);
-
-/*!
- * \brief Call this to free an iterator created by parking_lot_iterator_create
- */
-void parking_lot_iterator_destroy(struct ao2_iterator *iter);
-
-/*!
- * \brief Find a parking lot based on its name
- *
- * \param lot_name Name of the parking lot sought
- *
- * \retval The parking lot if found
- * \retval NULL if no parking lot with the name specified exists
- *
- * \note This reference will need to be free'd when you are done using it.
- */
-struct parking_lot *parking_lot_get(const char *lot_name);
-
-/*!
- * \brief Get the parkinglot that a channel should be parked in
- *
- * \param chan Channel which a parkinglot is sought for
- *
- * \retval The parking lot that the channel should go into
- * \retval NULL if the parking lot that the channel is designated to
- *         enter does not exist.
- *
- * \note This reference will need to be free'd when you are done using it.
- */
-struct parking_lot *channel_find_parkinglot(struct ast_channel *chan);
-
-/*!
+struct ao2_iterator *parking_lot_state_iterator_create(void);
+
+/*!
+ * \since 12
+ * \brief Call this to free an iterator created by parking_lot_state_iterator_create
+ */
+void parking_lot_state_iterator_destroy(struct ao2_iterator *iter);
+
+/*!
+ * \since 12
+ * \brief Find a parking lot state based on its name
+ *
+ * \param lot_name Name of the parking lot state sought
+ *
+ * \retval The parking lot state if found
+ * \retval NULL if no parking lot state with the name specified exists
+ *
+ * \note ao2_cleanup this reference when you are done using it or you'll cause leaks.
+ */
+struct parking_lot_state *parking_lot_find_by_name(const char *lot_name);
+
+/*!
+ * \since 12
+ * \brief Get the parkinglot state that a channel should be parked in
+ *
+ * \param chan Channel which a parkinglot state is sought for
+ *
+ * \retval The parking lot state that the channel should go into
+ * \retval NULL if the parking lot state that the channel is designated to
+ *         enter does not exist or can not accept parking lots
+ *
+ * \note ao2_cleanup this reference when you are done using it or you'll cause leaks.
+ */
+struct parking_lot_state *channel_find_parkinglot(struct ast_channel *chan);
+
+/*!
+ * \since 12
  * \brief Create a parked user within the specified parking lot and get a reference to it.
  *
- * \param lot The parking lot we are assigning the user to
+ * \param lot_state The parking lot state we are assigning the user to
  * \param parkee The channel being parked
  * \param parker The channel performing the park operation (may be the same channel)
  * \param use_random_space if true, prioritize using a random parking space instead
@@ -204,11 +269,12 @@
  * \retval NULL on failure
  * \retval reference to the parked user
  *
- * \note This reference will need to be free'd when you are done using it.
- */
-struct parked_user *generate_parked_user(struct parking_lot *lot, struct ast_channel *parkee, struct ast_channel *parker, int use_random_space, int time_limit);
-
-/*!
+ * \note ao2_cleanup this reference when you are done using it or you'll cause leaks.
+ */
+struct parked_user *generate_parked_user(struct parking_lot_state *lot_state, struct ast_channel *parkee, struct ast_channel *parker, int use_random_space, int time_limit);
+
+/*!
+ * \since 12
  * \brief Reset the start time of a parked user to now
  *
  * \param pu Parked user having the time reset
@@ -221,17 +287,19 @@
 void reset_parked_time(struct parked_user *pu);
 
 /*!
+ * \since 12
  * \brief Set a channel's position in the PBX after timeout using the parking lot settings
  *
  * \param pu Parked user who is entering/reentering the PBX
- * \param lot Parking lot the user was removed from.
+ * \param lot_state Parking lot state the user was removed from.
  *
  * \retval 0 Position set successfully
  * \retval -1 Failed to set the position
  */
-int comeback_goto(struct parked_user *pu, struct parking_lot *lot);
-
-/*!
+int comeback_goto(struct parked_user *pu, struct parking_lot_state *lot_state);
+
+/*!
+ * \since 12
  * \brief Pull a parked user out of its parking lot.
  * \param user The parked user being pulled.
  *
@@ -241,6 +309,7 @@
 int unpark_parked_user(struct parked_user *user);
 
 /*!
+ * \since 12
  * \brief Publish a stasis parked call message for a given parked user
  *
  * \param pu pointer to a parked_user that we are generating the message for
@@ -249,27 +318,38 @@
 void publish_parked_call(struct parked_user *pu, enum ast_parked_call_event_type event_type);
 
 /*!
- * \brief Publish a stasis parking lot message for a given parking lot
- *
- * \param lot pointer to a parking lot that we are generating the message for
- */
-void publish_parking_lot(struct parking_lot *lot);
-
-/*!
- * \brief Get a pointer to the Park application function.
- *
- * \retval Pointer to the Park application function
- */
-void *parking_get_park_app_cb(void);
-
-/*!
+ * \since 12
+ * \brief Publish a stasis parking lot message for a given parking lot state object
+ *
+ * \param lot pointer to a parking lot state object that we are generating the message for
+ */
+void publish_parking_lot_state(struct parking_lot_state *lot);
+
+/*!
+ * \since 12
+ * \brief Execution function for the parking application
+ *
+ * \param chan ast_channel entering the application
+ * \param data arguments to the application
+ *
+ * \retval 0 the application executed in such a way that the channel should proceed in the dial plan
+ * \retval -1 the channel should no longer proceed through the dial plan
+ *
+ * \note this function should only be used to register the parking application and not generally to park calls.
+ */
+int park_app_exec(struct ast_channel *chan, const char *data);
+
+/*!
+ * \since 12
  * \brief Register CLI commands and manager actions
+ *
  * \retval 0 if successful
  * \retval -1 on failure
  */
-int load_tools(void);
-
-/*!
+int load_parking_ui(void);
+
+/*!
+ * \since 12
  * \brief Unregister CLI commands and manager actions
  */
-void unload_tools(void);
+void unload_parking_ui(void);

Modified: team/jrose/bridge_projects/res/res_parking.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/res_parking.c?view=diff&rev=383612&r1=383611&r2=383612
==============================================================================
--- team/jrose/bridge_projects/res/res_parking.c (original)
+++ team/jrose/bridge_projects/res/res_parking.c Fri Mar 22 14:28:49 2013
@@ -50,6 +50,9 @@
 				</configOption>
 				<configOption name="parkingtime" default="45">
 					<synopsis>Amount of time a call will remain parked before giving up (in seconds).</synopsis>
+				</configOption>
+				<configOption name="parkedmusicclass">
+					<synopsis>Which music class to use for parked calls. They will use the default if unspecified.</synopsis>
 				</configOption>
 				<configOption name="comebacktoorigin" default="yes">
 					<synopsis>Determines what should be done with the parked channel if no one picks it up before it times out.</synopsis>
@@ -113,40 +116,36 @@
 					<synopsis>Who we should play the courtesytone to on the pickup of a parked call from this lot</synopsis>
 					<description>
 						<enumlist>
+							<enum name="no"><para>Apply to neither side.</para></enum>
 							<enum name="caller"><para>Apply to only to the caller picking up the parked call.</para></enum>
 							<enum name="callee"><para>Apply to only to the parked call being picked up.</para></enum>
 							<enum name="both"><para>Apply to both the caller and the callee.</para></enum>
 						</enumlist>
-						<note><para>If courtesy tone is not specified then this option will be ignored. If any value not listed above
-							is used then the coutesy tone will not be played to either side.</para></note>
-					</description>
-				</configOption>
-				<configOption name="parkedcalltransfers" default="none">
+						<note><para>If courtesy tone is not specified then this option will be ignored.</para></note>
+					</description>
+				</configOption>
+				<configOption name="parkedcalltransfers" default="no">
 					<synopsis>Apply the DTMF transfer features to the caller and/or callee when parked calls are picked up.</synopsis>
 					<description>
 						<xi:include xpointer="xpointer(/docs/configInfo[@name='res_parking']/configFile[@name='res_parking.conf']/configObject[@name='parking_lot']/configOption[@name='parkedplay']/description/enumlist)" />
-						<note><para>If any value not listed above is used, this feature is applied to neither side</para></note>
-					</description>
-				</configOption>
-				<configOption name="parkedcallreparking" default="none">
+					</description>
+				</configOption>
+				<configOption name="parkedcallreparking" default="no">
 					<synopsis>Apply the DTMF parking feature to the caller and/or callee when parked calls are picked up.</synopsis>
 					<description>
 						<xi:include xpointer="xpointer(/docs/configInfo[@name='res_parking']/configFile[@name='res_parking.conf']/configObject[@name='parking_lot']/configOption[@name='parkedplay']/description/enumlist)" />
-						<xi:include xpointer="xpointer(/docs/configInfo[@name='res_parking']/configFile[@name='res_parking.conf']/configObject[@name='parking_lot']/configOption[@name='parkedcalltransfers']/description/note)" />
-					</description>
-				</configOption>
-				<configOption name="parkedcallhangup" default="none">
+					</description>
+				</configOption>
+				<configOption name="parkedcallhangup" default="no">
 					<synopsis>Apply the DTMF Hangup feature to the caller and/or callee when parked calls are picked up.</synopsis>
 					<description>
 						<xi:include xpointer="xpointer(/docs/configInfo[@name='res_parking']/configFile[@name='res_parking.conf']/configObject[@name='parking_lot']/configOption[@name='parkedplay']/description/enumlist)" />
-						<xi:include xpointer="xpointer(/docs/configInfo[@name='res_parking']/configFile[@name='res_parking.conf']/configObject[@name='parking_lot']/configOption[@name='parkedcalltransfers']/description/note)" />
-					</description>
-				</configOption>
-				<configOption name="parkedcallrecording" default="none">
+					</description>
+				</configOption>
+				<configOption name="parkedcallrecording" default="no">
 					<synopsis>Apply the DTMF recording features to the caller and/or callee when parked calls are picked up</synopsis>
 					<description>
 						<xi:include xpointer="xpointer(/docs/configInfo[@name='res_parking']/configFile[@name='res_parking.conf']/configObject[@name='parking_lot']/configOption[@name='parkedplay']/description/enumlist)" />
-						<xi:include xpointer="xpointer(/docs/configInfo[@name='res_parking']/configFile[@name='res_parking.conf']/configObject[@name='parking_lot']/configOption[@name='parkedcalltransfers']/description/note)" />
 					</description>
 				</configOption>
 				<configOption name="findslot" default="first">
@@ -182,55 +181,12 @@
 #include "asterisk/features.h"
 #include "asterisk/manager.h"
 
-static void *parking_lot_config_alloc(void);
-static void *parking_lot_alloc(const char *cat);
-static void *parking_lot_find(struct ao2_container *container, const char *cat);
-
-struct parking_global_config {
-	int parkeddynamic; /* XXX This feature still needs to be implemented. Entirely. */
-};
-
-struct parking_lot_config {
-	struct parking_global_config *global;
-	struct ao2_container *parking_lot_list;
-};
-
-static struct aco_type global_option = {
-	.type = ACO_GLOBAL,
-	.name = "globals",
-	.item_offset = offsetof(struct parking_lot_config, global),
-	.category_match = ACO_WHITELIST,
-	.category = "^general$",
-};
-
-struct aco_type *global_options[] = ACO_TYPES(&global_option);
-
-static struct aco_type parking_lot_type = {
-	.type = ACO_ITEM,
-	.name = "parking_lot",
-	.category_match = ACO_BLACKLIST,
-	.category = "^(general)$",
-	.item_alloc = parking_lot_alloc,
-	.item_find = parking_lot_find,
-	.item_offset = offsetof(struct parking_lot_config, parking_lot_list),
-};
-
-struct aco_type *parking_lot_types[] = ACO_TYPES(&parking_lot_type);
-
-struct aco_file parking_lot_conf = {
-	.filename = "res_parking.conf",
-	.types = ACO_TYPES(&global_option, &parking_lot_type),
-};
-
-static AO2_GLOBAL_OBJ_STATIC(globals);
-
-CONFIG_INFO_STANDARD(cfg_info, globals, parking_lot_config_alloc,
-	.files = ACO_FILES(&parking_lot_conf),
-);
-
-static int parking_lot_hash_fn(const void *obj, const int flags)
-{
-	const struct parking_lot *entry;
+#define app_park "Park"
+#define app_parkedcall "ParkedCall"
+

[... 731 lines stripped ...]



More information about the asterisk-commits mailing list