[asterisk-commits] kmoore: trunk r396890 - in /trunk: channels/ include/asterisk/ main/ res/ res...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Aug 17 10:01:59 CDT 2013


Author: kmoore
Date: Sat Aug 17 10:01:54 2013
New Revision: 396890

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=396890
Log:
Allow res_parking to be unloadable

This change protects accesses of res_parking such that it can unload
safely once transient uses of its registered functions are complete.
The parking API has been restructured such that its consumers do not
have access to the vtable exposed by the parking provider, but instead
route through stubs to prevent consumers from holding on to function
pointers.

This adds calls to all the parking unload functions and moves
application loading and unloading into functions in
parking_applications.c similar to the rest of the parts of res_parking.

Review: https://reviewboard.asterisk.org/r/2763/
(closes issue ASTERISK-22142)

Modified:
    trunk/channels/chan_dahdi.c
    trunk/channels/chan_skinny.c
    trunk/channels/sig_analog.c
    trunk/include/asterisk/parking.h
    trunk/main/bridge.c
    trunk/main/bridge_channel.c
    trunk/main/parking.c
    trunk/res/parking/parking_applications.c
    trunk/res/parking/parking_bridge_features.c
    trunk/res/parking/res_parking.h
    trunk/res/res_parking.c

Modified: trunk/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_dahdi.c?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/channels/chan_dahdi.c (original)
+++ trunk/channels/chan_dahdi.c Sat Aug 17 10:01:54 2013
@@ -9245,10 +9245,6 @@
 	int idx;
 	struct ast_format tmpfmt;
 	RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
-	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, parking_provider,
-		ast_parking_get_bridge_features(),
-		ao2_cleanup);
-	int is_exten_parking;
 	const char *pickupexten;
 
 	ast_mutex_lock(&ss_thread_lock);
@@ -9562,6 +9558,8 @@
 		if (p->subs[SUB_THREEWAY].owner)
 			timeout = 999999;
 		while (len < AST_MAX_EXTENSION-1) {
+			int is_exten_parking = 0;
+
 			/* Read digit unless it's supposed to be immediate, in which case the
 			   only answer is 's' */
 			if (p->immediate)
@@ -9584,7 +9582,9 @@
 			} else {
 				tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
 			}
-			is_exten_parking = (parking_provider ? parking_provider->parking_is_exten_park(ast_channel_context(chan), exten) : 0);
+			if (ast_parking_provider_registered()) {
+				is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
+			}
 			if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
 				if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
 					if (getforward) {
@@ -9729,7 +9729,7 @@
 				ast_channel_lock(chan);
 				bridge_channel = ast_channel_get_bridge_channel(chan);
 				ast_channel_unlock(chan);
-				if (bridge_channel && !parking_provider->parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) {
+				if (bridge_channel && !ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) {
 					ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
 				}
 				break;

Modified: trunk/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_skinny.c?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/channels/chan_skinny.c (original)
+++ trunk/channels/chan_skinny.c Sat Aug 17 10:01:54 2013
@@ -6408,14 +6408,11 @@
 		{
 		char extout[AST_MAX_EXTENSION];
 		char message[32];
-		RAII_VAR(struct ast_parking_bridge_feature_fn_table *, parking_provider,
-			ast_parking_get_bridge_features(),
-			ao2_cleanup);
 		RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
 		SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_CALLPARK from %s, inst %d, callref %d\n",
 			d->name, instance, callreference);
 
-		if (!parking_provider) {
+		if (!ast_parking_provider_registered()) {
 			transmit_displaynotify(d, "Call Park not available", 10);
 			break;
 		}
@@ -6431,7 +6428,7 @@
 				break;
 			}
 
-			if (!parking_provider->parking_park_call(bridge_channel, extout, sizeof(extout))) {
+			if (!ast_parking_park_call(bridge_channel, extout, sizeof(extout))) {
 				snprintf(message, sizeof(message), "Call Parked at: %s", extout);
 				transmit_displaynotify(d, message, 10);
 				break;
@@ -7158,14 +7155,11 @@
 		{
 		char extout[AST_MAX_EXTENSION];
 		char message[32];
-		RAII_VAR(struct ast_parking_bridge_feature_fn_table *, parking_provider,
-			ast_parking_get_bridge_features(),
-			ao2_cleanup);
 		RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
 		SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_PARK from %s, inst %d, callref %d\n",
 			d->name, instance, callreference);
 
-		if (!parking_provider) {
+		if (!ast_parking_provider_registered()) {
 			transmit_displaynotify(d, "Call Park not available", 10);
 			break;
 		}
@@ -7183,7 +7177,7 @@
 				break;
 			}
 
-			if (!parking_provider->parking_park_call(bridge_channel, extout, sizeof(extout))) {
+			if (!ast_parking_park_call(bridge_channel, extout, sizeof(extout))) {
 				snprintf(message, sizeof(message), "Call Parked at: %s", extout);
 				transmit_displaynotify(d, message, 10);
 				break;

Modified: trunk/channels/sig_analog.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sig_analog.c?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/channels/sig_analog.c (original)
+++ trunk/channels/sig_analog.c Sat Aug 17 10:01:54 2013
@@ -1715,11 +1715,7 @@
 	int idx;
 	struct ast_callid *callid;
 	RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
-	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, parking_provider,
-		ast_parking_get_bridge_features(),
-		ao2_cleanup);
 	const char *pickupexten;
-	int is_exten_parking;
 
 	analog_increase_ss_count();
 
@@ -2077,6 +2073,8 @@
 			timeout = 999999;
 		}
 		while (len < AST_MAX_EXTENSION-1) {
+			int is_exten_parking = 0;
+
 			/* Read digit unless it's supposed to be immediate, in which case the
 			   only answer is 's' */
 			if (p->immediate) {
@@ -2100,7 +2098,9 @@
 			} else {
 				analog_play_tone(p, idx, ANALOG_TONE_DIALTONE);
 			}
-			is_exten_parking = (parking_provider ? parking_provider->parking_is_exten_park(ast_channel_context(chan), exten) : 0);
+			if (ast_parking_provider_registered()) {
+				is_exten_parking = ast_parking_is_exten_park(ast_channel_context(chan), exten);
+			}
 			if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !is_exten_parking) {
 				if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
 					if (getforward) {
@@ -2253,7 +2253,7 @@
 				ast_channel_lock(chan);
 				bridge_channel = ast_channel_get_bridge_channel(chan);
 				ast_channel_unlock(chan);
-				if (bridge_channel && !parking_provider->parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) {
+				if (bridge_channel && !ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) {
 					ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
 				}
 				ao2_ref(bridge_channel, -1);

Modified: trunk/include/asterisk/parking.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/parking.h?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/include/asterisk/parking.h (original)
+++ trunk/include/asterisk/parking.h Sat Aug 17 10:01:54 2013
@@ -114,6 +114,8 @@
 
 #define PARKING_MODULE_VERSION 1
 
+struct ast_module_info;
+
 /*!
  * \brief A function table providing parking functionality to the \ref AstBridging
  * Bridging API and other consumers
@@ -188,15 +190,67 @@
 	 * \retval non-zero on error
 	 */
 	int (* parking_park_bridge_channel)(struct ast_bridge_channel *parkee, const char *parkee_uuid, const char *parker_uuid, const char *app_data);
+
+	/*! \brief The module info for the module registering this parking provider */
+	const struct ast_module_info *module_info;
 };
 
 /*!
- * \brief Obtain the current parking provider
- *
- * \retval NULL if no provider exists
- * \retval an ao2 ref counted object of the existing provider's function table
- */
-struct ast_parking_bridge_feature_fn_table *ast_parking_get_bridge_features(void);
+ * \brief Determine if the context/exten is a "parking" extension
+ *
+ * \retval 0 if the extension is not a parking extension
+ * \retval 1 if the extension is a parking extension
+ */
+int ast_parking_is_exten_park(const char *context, const char *exten);
+
+/*!
+ * \brief Park the bridge and/or callers that this channel is in
+ *
+ * \param parker The bridge_channel parking the bridge
+ * \param exten Optional. The extension the channel or bridge was parked at if the
+ * call succeeds.
+ * \param length Optional. If \c exten is specified, the size of the buffer.
+ *
+ * \note This is safe to be called outside of the \ref AstBridging Bridging API.
+ *
+ * \retval 0 on success
+ * \retval non-zero on error
+ */
+int ast_parking_park_call(struct ast_bridge_channel *parker, char *exten, size_t length);
+
+/*!
+ * \brief Perform a blind transfer to a parking extension.
+ *
+ * \param parker The \ref bridge_channel object that is initiating the parking
+ * \param context The context to blind transfer to
+ * \param exten The extension to blind transfer to
+ *
+ * \note If the bridge \ref parker is in has more than one other occupant, the entire
+ * bridge will be parked using a Local channel
+ *
+ * \note This is safe to be called outside of the \ref AstBridging Bridging API.
+ *
+ * \retval 0 on success
+ * \retval non-zero on error
+ */
+int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten);
+
+/*!
+ * \brief Perform a direct park on a channel in a bridge.
+ *
+ * \param parkee The channel in the bridge to be parked.
+ * \param parkee_uuid The UUID of the channel being packed.
+ * \param parker_uuid The UUID of the channel performing the park.
+ * \param app_data Data to pass to the Park application
+ *
+ * \note This must be called within the context of the \ref AstBridging Bridging API.
+ * External entities should not call this method directly, but should instead use
+ * the direct call parking method or the blind transfer method.
+ *
+ * \retval 0 on success
+ * \retval non-zero on error
+ */
+int ast_parking_park_bridge_channel(struct ast_bridge_channel *parkee, const char *parkee_uuid, const char *parker_uuid, const char *app_data);
 
 /*!
  * \brief Register a parking provider
@@ -217,3 +271,11 @@
  * \retval -1 on error
  */
 int ast_parking_unregister_bridge_features(const char *module_name);
+
+/*!
+ * \brief Check whether a parking provider is registered
+ *
+ * \retval 0 if there is no parking provider regsistered
+ * \retval 1 if there is a parking provider regsistered
+ */
+int ast_parking_provider_registered(void);

Modified: trunk/main/bridge.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridge.c?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/main/bridge.c (original)
+++ trunk/main/bridge.c Sat Aug 17 10:01:54 2013
@@ -3844,11 +3844,8 @@
 static enum ast_transfer_result try_parking(struct ast_channel *transferer, const char *context, const char *exten)
 {
 	RAII_VAR(struct ast_bridge_channel *, transferer_bridge_channel, NULL, ao2_cleanup);
-	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, parking_provider,
-		ast_parking_get_bridge_features(),
-		ao2_cleanup);
-
-	if (!parking_provider) {
+
+	if (!ast_parking_provider_registered()) {
 		return AST_BRIDGE_TRANSFER_FAIL;
 	}
 
@@ -3860,7 +3857,7 @@
 		return AST_BRIDGE_TRANSFER_FAIL;
 	}
 
-	if (parking_provider->parking_blind_transfer_park(transferer_bridge_channel,
+	if (ast_parking_blind_transfer_park(transferer_bridge_channel,
 		context, exten)) {
 		return AST_BRIDGE_TRANSFER_FAIL;
 	}

Modified: trunk/main/bridge_channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridge_channel.c?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/main/bridge_channel.c (original)
+++ trunk/main/bridge_channel.c Sat Aug 17 10:01:54 2013
@@ -754,17 +754,13 @@
  */
 static void bridge_channel_park(struct ast_bridge_channel *bridge_channel, struct bridge_park *payload)
 {
-	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, parking_provider,
-		ast_parking_get_bridge_features(),
-		ao2_cleanup);
-
-	if (!parking_provider) {
+	if (!ast_parking_provider_registered()) {
 		ast_log(AST_LOG_WARNING, "Unable to park %s: No parking provider loaded!\n",
 			ast_channel_name(bridge_channel->chan));
 		return;
 	}
 
-	if (parking_provider->parking_park_bridge_channel(bridge_channel, payload->parkee_uuid,
+	if (ast_parking_park_bridge_channel(bridge_channel, payload->parkee_uuid,
 		&payload->parkee_uuid[payload->parker_uuid_offset],
 		payload->app_data_offset ? &payload->parkee_uuid[payload->app_data_offset] : NULL)) {
 		ast_log(AST_LOG_WARNING, "Error occurred while parking %s\n",

Modified: trunk/main/parking.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/parking.c?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/main/parking.c (original)
+++ trunk/main/parking.c Sat Aug 17 10:01:54 2013
@@ -34,6 +34,7 @@
 #include "asterisk/parking.h"
 #include "asterisk/channel.h"
 #include "asterisk/_private.h"
+#include "asterisk/module.h"
 
 /*! \brief Message type for parked calls */
 STASIS_MESSAGE_TYPE_DEFN(ast_parked_call_type);
@@ -124,19 +125,77 @@
 	return payload;
 }
 
-struct ast_parking_bridge_feature_fn_table *ast_parking_get_bridge_features(void)
-{
-	return (struct ast_parking_bridge_feature_fn_table*)ao2_global_obj_ref(parking_provider);
-}
-
-/*! \brief A wrapper around the fn_table to ao2-ify it */
-struct parking_provider_wrapper {
-	struct ast_parking_bridge_feature_fn_table fn_table;
-};
+int ast_parking_park_bridge_channel(struct ast_bridge_channel *parkee, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
+{
+	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
+		ao2_global_obj_ref(parking_provider), ao2_cleanup);
+
+	if (!table || !table->parking_park_bridge_channel) {
+		return -1;
+	}
+
+	if (table->module_info) {
+		SCOPED_MODULE_USE(table->module_info->self);
+		return table->parking_park_bridge_channel(parkee, parkee_uuid, parker_uuid, app_data);
+	}
+
+	return table->parking_park_bridge_channel(parkee, parkee_uuid, parker_uuid, app_data);
+}
+
+int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten)
+{
+	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
+		ao2_global_obj_ref(parking_provider), ao2_cleanup);
+
+	if (!table || !table->parking_blind_transfer_park) {
+		return -1;
+	}
+
+	if (table->module_info) {
+		SCOPED_MODULE_USE(table->module_info->self);
+		return table->parking_blind_transfer_park(parker, context, exten);
+	}
+
+	return table->parking_blind_transfer_park(parker, context, exten);
+}
+
+int ast_parking_park_call(struct ast_bridge_channel *parker, char *exten, size_t length)
+{
+	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
+		ao2_global_obj_ref(parking_provider), ao2_cleanup);
+
+	if (!table || !table->parking_park_call) {
+		return -1;
+	}
+
+	if (table->module_info) {
+		SCOPED_MODULE_USE(table->module_info->self);
+		return table->parking_park_call(parker, exten, length);
+	}
+
+	return table->parking_park_call(parker, exten, length);
+}
+
+int ast_parking_is_exten_park(const char *context, const char *exten)
+{
+	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
+		ao2_global_obj_ref(parking_provider), ao2_cleanup);
+
+	if (!table || !table->parking_is_exten_park) {
+		return -1;
+	}
+
+	if (table->module_info) {
+		SCOPED_MODULE_USE(table->module_info->self);
+		return table->parking_is_exten_park(context, exten);
+	}
+
+	return table->parking_is_exten_park(context, exten);
+}
 
 int ast_parking_register_bridge_features(struct ast_parking_bridge_feature_fn_table *fn_table)
 {
-	RAII_VAR(struct parking_provider_wrapper *, wrapper,
+	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, wrapper,
 		ao2_global_obj_ref(parking_provider), ao2_cleanup);
 
 	if (fn_table->module_version != PARKING_MODULE_VERSION) {
@@ -147,7 +206,7 @@
 
 	if (wrapper) {
 		ast_log(AST_LOG_WARNING, "Parking provider already registered by %s!\n",
-			wrapper->fn_table.module_name);
+			wrapper->module_name);
 		return -1;
 	}
 
@@ -155,7 +214,7 @@
 	if (!wrapper) {
 		return -1;
 	}
-	wrapper->fn_table = *fn_table;
+	*wrapper = *fn_table;
 
 	ao2_global_obj_replace(parking_provider, wrapper);
 	return 0;
@@ -163,15 +222,14 @@
 
 int ast_parking_unregister_bridge_features(const char *module_name)
 {
-	RAII_VAR(struct parking_provider_wrapper *, wrapper,
+	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, wrapper,
 		ao2_global_obj_ref(parking_provider), ao2_cleanup);
 
 	if (!wrapper) {
-		ast_log(AST_LOG_WARNING, "No parking provider to unregister\n");
-		return -1;
-	}
-
-	if (strcmp(wrapper->fn_table.module_name, module_name)) {
+		return -1;
+	}
+
+	if (strcmp(wrapper->module_name, module_name)) {
 		ast_log(AST_LOG_WARNING, "%s has not registered the parking provider\n", module_name);
 		return -1;
 	}
@@ -179,3 +237,11 @@
 	ao2_global_obj_replace_unref(parking_provider, NULL);
 	return 0;
 }
+
+int ast_parking_provider_registered(void)
+{
+	RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
+		ao2_global_obj_ref(parking_provider), ao2_cleanup);
+
+	return !!table;
+}

Modified: trunk/res/parking/parking_applications.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/parking/parking_applications.c?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/res/parking/parking_applications.c (original)
+++ trunk/res/parking/parking_applications.c Sat Aug 17 10:01:54 2013
@@ -194,6 +194,8 @@
 	</application>
  ***/
 
+#define PARK_AND_ANNOUNCE_APPLICATION "ParkAndAnnounce"
+
 /* Park a call */
 
 enum park_args {
@@ -488,7 +490,7 @@
 
 }
 
-int park_app_exec(struct ast_channel *chan, const char *data)
+static int park_app_exec(struct ast_channel *chan, const char *data)
 {
 	RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
 
@@ -547,7 +549,7 @@
 
 /* Retrieve a parked call */
 
-int parked_call_app_exec(struct ast_channel *chan, const char *data)
+static int parked_call_app_exec(struct ast_channel *chan, const char *data)
 {
 	RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
 	RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup); /* Parked user being retrieved */
@@ -765,7 +767,7 @@
 	*dial_string = '\0'; /* If we observe this dial string on a second pass, we don't want to do anything with it. */
 }
 
-int park_and_announce_app_exec(struct ast_channel *chan, const char *data)
+static int park_and_announce_app_exec(struct ast_channel *chan, const char *data)
 {
 	struct ast_bridge_features chan_features;
 	char *parse;
@@ -857,3 +859,29 @@
 
 	return res;
 }
+
+int load_parking_applications(void)
+{
+	const struct ast_module_info *ast_module_info = parking_get_module_info();
+
+	if (ast_register_application_xml(PARK_APPLICATION, park_app_exec)) {
+		return -1;
+	}
+
+	if (ast_register_application_xml(PARKED_CALL_APPLICATION, parked_call_app_exec)) {
+		return -1;
+	}
+
+	if (ast_register_application_xml(PARK_AND_ANNOUNCE_APPLICATION, park_and_announce_app_exec)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+void unload_parking_applications(void)
+{
+	ast_unregister_application(PARK_APPLICATION);
+	ast_unregister_application(PARKED_CALL_APPLICATION);
+	ast_unregister_application(PARK_AND_ANNOUNCE_APPLICATION);
+}

Modified: trunk/res/parking/parking_bridge_features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/parking/parking_bridge_features.c?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/res/parking/parking_bridge_features.c (original)
+++ trunk/res/parking/parking_bridge_features.c Sat Aug 17 10:01:54 2013
@@ -40,6 +40,7 @@
 #include "asterisk/say.h"
 #include "asterisk/datastore.h"
 #include "asterisk/stasis.h"
+#include "asterisk/module.h"
 #include "asterisk/core_local.h"
 
 struct parked_subscription_datastore {
@@ -444,6 +445,8 @@
 
 static int feature_park_call(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 {
+	SCOPED_MODULE_USE(parking_get_module_info()->self);
+
 	return parking_park_call(bridge_channel, NULL, 0);
 }
 
@@ -623,10 +626,15 @@
 
 int load_parking_bridge_features(void)
 {
+	parking_provider.module_info = parking_get_module_info();
+
 	if (ast_parking_register_bridge_features(&parking_provider)) {
 		return -1;
 	}
 
-	ast_bridge_features_register(AST_BRIDGE_BUILTIN_PARKCALL, feature_park_call, NULL);
+	if (ast_bridge_features_register(AST_BRIDGE_BUILTIN_PARKCALL, feature_park_call, NULL)) {
+		return -1;
+	}
+
 	return 0;
 }

Modified: trunk/res/parking/res_parking.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/parking/res_parking.h?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/res/parking/res_parking.h (original)
+++ trunk/res/parking/res_parking.h Sat Aug 17 10:01:54 2013
@@ -32,6 +32,7 @@
 #define DEFAULT_PARKING_EXTEN "700"
 #define BASE_REGISTRAR "res_parking"
 #define PARK_DIAL_CONTEXT "park-dial"
+#define PARKED_CALL_APPLICATION "ParkedCall"
 
 enum park_call_resolution {
 	PARK_UNSET = 0,		/*! Nothing set a resolution. This should never be observed in practice. */
@@ -463,51 +464,26 @@
 
 /*!
  * \since 12.0.0
- * \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.0.0
- * \brief Execution function for the parked call 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
- */
-int parked_call_app_exec(struct ast_channel *chan, const char *data);
-
-/*!
- * \since 12.0.0
- * \brief Execution function for the park and retrieve 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 park and announce application and not generally to park and announce.
- */
-int park_and_announce_app_exec(struct ast_channel *chan, const char *data);
-
-/*!
- * \since 12.0.0
- * \brief Register CLI commands
+ * \brief Register parking applications
  *
  * \retval 0 if successful
  * \retval -1 on failure
  */
+int load_parking_applications(void);
+
+/*!
+ * \since 12.0.0
+ * \brief Unregister parking applications
+ */
+void unload_parking_applications(void);
+
+/*!
+ * \since 12.0.0
+ * \brief Register CLI commands
+ *
+ * \retval 0 if successful
+ * \retval -1 on failure
+ */
 int load_parking_ui(void);
 
 /*!
@@ -571,3 +547,12 @@
  * \return Nothing
  */
 void unload_parking_tests(void);
+
+struct ast_module_info;
+/*!
+ * \since 12.0.0
+ * \brief Get res_parking's module info
+ *
+ * \retval res_parking's ast_module
+ */
+const struct ast_module_info *parking_get_module_info(void);

Modified: trunk/res/res_parking.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_parking.c?view=diff&rev=396890&r1=396889&r2=396890
==============================================================================
--- trunk/res/res_parking.c (original)
+++ trunk/res/res_parking.c Sat Aug 17 10:01:54 2013
@@ -33,6 +33,9 @@
 		<configFile name="res_parking.conf">
 			<configObject name="globals">
 				<synopsis>Options that apply to every parking lot</synopsis>
+				<configOption name="parkeddynamic">
+					<synopsis>Enables dynamically created parkinglots.</synopsis>
+				</configOption>
 			</configObject>
 			<configObject name="parking_lot">
 				<synopsis>Defined parking lots for res_parking to use to park calls on</synopsis>
@@ -192,9 +195,6 @@
 #include "asterisk/manager.h"
 #include "asterisk/pbx.h"
 
-#define PARKED_CALL_APPLICATION "ParkedCall"
-#define PARK_AND_ANNOUNCE_APPLICATION "ParkAndAnnounce"
-
 static int parking_lot_sort_fn(const void *obj_left, const void *obj_right, int flags)
 {
 	const struct parking_lot *left = obj_left;
@@ -1152,6 +1152,27 @@
 	disable_marked_lots();
 }
 
+const struct ast_module_info *parking_get_module_info(void)
+{
+	return ast_module_info;
+}
+
+static int unload_module(void)
+{
+	unload_parking_bridge_features();
+	remove_all_configured_parking_lot_extensions();
+	unload_parking_applications();
+	unload_parking_manager();
+	unload_parking_ui();
+	unload_parking_devstate();
+	unload_parking_tests();
+	ao2_cleanup(parking_lot_container);
+	parking_lot_container = NULL;
+	aco_info_destroy(&cfg_info);
+
+	return 0;
+}
+
 static int load_module(void)
 {
 	parking_lot_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX,
@@ -1194,15 +1215,7 @@
 		goto error;
 	}
 
-	if (ast_register_application_xml(PARK_APPLICATION, park_app_exec)) {
-		goto error;
-	}
-
-	if (ast_register_application_xml(PARKED_CALL_APPLICATION, parked_call_app_exec)) {
-		goto error;
-	}
-
-	if (ast_register_application_xml(PARK_AND_ANNOUNCE_APPLICATION, park_and_announce_app_exec)) {
+	if (load_parking_applications()) {
 		goto error;
 	}
 
@@ -1229,9 +1242,7 @@
 	return AST_MODULE_LOAD_SUCCESS;
 
 error:
-	/* XXX errored loads don't currently do a good job of cleaning up after themselves */
-	ao2_cleanup(parking_lot_container);
-	aco_info_destroy(&cfg_info);
+	unload_module();
 	return AST_MODULE_LOAD_DECLINE;
 }
 
@@ -1242,25 +1253,6 @@
 	}
 
 	return 0;
-}
-
-static int unload_module(void)
-{
-
-	/*ast_parking_unregister_bridge_features(parking_provider.module_name);*/
-
-	/* XXX Parking is currently not unloadable due to the fact that it loads features which could cause
-	 *     significant problems if they disappeared while a channel still had access to them.
-	 */
-	return -1;
-
-	/* TODO Things we will need to do here:
-	 *
-	 *  destroy existing parking lots
-	 *  uninstall parking related bridge features
-	 *  remove extensions owned by the parking registrar
-	 *  unload currently loaded unit tests, CLI/AMI commands, etc.
-	 */
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Call Parking Resource",




More information about the asterisk-commits mailing list