summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
authorKinsey Moore <kmoore@digium.com>2013-08-17 15:01:54 +0000
committerKinsey Moore <kmoore@digium.com>2013-08-17 15:01:54 +0000
commit56aea1c030a6ee322446b5c687da164246b0c0d5 (patch)
tree5c7729fcff1c8660d559f68a78f07d0fde579516 /res
parentd7f1f3127084e4b7b204141c0b40c28c327f74b0 (diff)
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) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396890 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res')
-rw-r--r--res/parking/parking_applications.c34
-rw-r--r--res/parking/parking_bridge_features.c10
-rw-r--r--res/parking/res_parking.h47
-rw-r--r--res/res_parking.c60
4 files changed, 82 insertions, 69 deletions
diff --git a/res/parking/parking_applications.c b/res/parking/parking_applications.c
index 4b854759d..29f38b4b8 100644
--- a/res/parking/parking_applications.c
+++ b/res/parking/parking_applications.c
@@ -194,6 +194,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</application>
***/
+#define PARK_AND_ANNOUNCE_APPLICATION "ParkAndAnnounce"
+
/* Park a call */
enum park_args {
@@ -488,7 +490,7 @@ struct ast_bridge *park_application_setup(struct ast_channel *parkee, struct ast
}
-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 @@ int park_app_exec(struct ast_channel *chan, const char *data)
/* 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 @@ static void park_announce_update_cb(void *data, struct stasis_subscription *sub,
*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 @@ int park_and_announce_app_exec(struct ast_channel *chan, const char *data)
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);
+}
diff --git a/res/parking/parking_bridge_features.c b/res/parking/parking_bridge_features.c
index de06dd96f..12d7d95f5 100644
--- a/res/parking/parking_bridge_features.c
+++ b/res/parking/parking_bridge_features.c
@@ -40,6 +40,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#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 parking_park_call(struct ast_bridge_channel *parker, char *exten, siz
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 @@ void unload_parking_bridge_features(void)
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;
}
diff --git a/res/parking/res_parking.h b/res/parking/res_parking.h
index 5dc99b796..f97e85be9 100644
--- a/res/parking/res_parking.h
+++ b/res/parking/res_parking.h
@@ -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,43 +464,18 @@ int parking_dynamic_lots_enabled(void);
/*!
* \since 12.0.0
- * \brief Execution function for the parking application
+ * \brief Register parking applications
*
- * \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
+ * \retval 0 if successful
+ * \retval -1 on failure
*/
-int parked_call_app_exec(struct ast_channel *chan, const char *data);
+int load_parking_applications(void);
/*!
* \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.
+ * \brief Unregister parking applications
*/
-int park_and_announce_app_exec(struct ast_channel *chan, const char *data);
+void unload_parking_applications(void);
/*!
* \since 12.0.0
@@ -571,3 +547,12 @@ int load_parking_tests(void);
* \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);
diff --git a/res/res_parking.c b/res/res_parking.c
index 3cd10a1dd..33cc56071 100644
--- a/res/res_parking.c
+++ b/res/res_parking.c
@@ -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 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#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 @@ static void link_configured_disable_marked_lots(void)
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 @@ static int load_module(void)
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 @@ static int load_module(void)
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;
}
@@ -1244,25 +1255,6 @@ static int reload_module(void)
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",
.load = load_module,
.unload = unload_module,