summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/confbridge/conf_config_parser.c6
-rw-r--r--include/asterisk/bridging_features.h12
-rw-r--r--main/bridging.c46
-rw-r--r--main/features.c7
-rw-r--r--res/parking/parking_bridge_features.c1
5 files changed, 61 insertions, 11 deletions
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index 042968c59..35d96ae31 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -2161,8 +2161,10 @@ int conf_set_menu_to_user(const char *menu_name, struct confbridge_user *user)
ao2_ref(menu, +1);
pvt->menu = menu;
- ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf, menu_hook_callback,
- pvt, menu_hook_destroy, 0);
+ if (ast_bridge_dtmf_hook(&user->features, pvt->menu_entry.dtmf,
+ menu_hook_callback, pvt, menu_hook_destroy, 0)) {
+ menu_hook_destroy(pvt);
+ }
}
ao2_unlock(menu);
diff --git a/include/asterisk/bridging_features.h b/include/asterisk/bridging_features.h
index 1ee13a46a..6399a22fc 100644
--- a/include/asterisk/bridging_features.h
+++ b/include/asterisk/bridging_features.h
@@ -390,7 +390,7 @@ int ast_bridge_interval_unregister(enum ast_bridge_builtin_interval interval);
* \param remove_flags Dictates what situations the hook should be removed.
*
* \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
*
* Example usage:
*
@@ -420,7 +420,7 @@ int ast_bridge_join_hook(struct ast_bridge_features *features,
* \param remove_flags Dictates what situations the hook should be removed.
*
* \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
*
* Example usage:
*
@@ -450,7 +450,7 @@ int ast_bridge_leave_hook(struct ast_bridge_features *features,
* \param remove_flags Dictates what situations the hook should be removed.
*
* \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
*
* Example usage:
*
@@ -481,7 +481,7 @@ int ast_bridge_hangup_hook(struct ast_bridge_features *features,
* \param remove_flags Dictates what situations the hook should be removed.
*
* \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
*
* Example usage:
*
@@ -503,7 +503,7 @@ int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
enum ast_bridge_hook_remove_flags remove_flags);
/*!
- * \brief attach an interval hook to a bridge features structure
+ * \brief Attach an interval hook to a bridge features structure
*
* \param features Bridge features structure
* \param interval The interval that the hook should execute at in milliseconds
@@ -513,7 +513,7 @@ int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
* \param remove_flags Dictates what situations the hook should be removed.
*
* \retval 0 on success
- * \retval -1 on failure
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
*
* \code
* struct ast_bridge_features features;
diff --git a/main/bridging.c b/main/bridging.c
index ad730f945..510123753 100644
--- a/main/bridging.c
+++ b/main/bridging.c
@@ -4893,6 +4893,15 @@ int ast_bridge_dtmf_hook(struct ast_bridge_features *features,
/* Once done we put it in the container. */
res = ao2_link(features->dtmf_hooks, hook) ? 0 : -1;
+ if (res) {
+ /*
+ * Could not link the hook into the container.
+ *
+ * Remove the hook_pvt destructor call from the hook since we
+ * are returning failure to install the hook.
+ */
+ hook->destructor = NULL;
+ }
ao2_ref(hook, -1);
return res;
@@ -4916,6 +4925,15 @@ int ast_bridge_hangup_hook(struct ast_bridge_features *features,
/* Once done we put it in the container. */
res = ao2_link(features->hangup_hooks, hook) ? 0 : -1;
+ if (res) {
+ /*
+ * Could not link the hook into the container.
+ *
+ * Remove the hook_pvt destructor call from the hook since we
+ * are returning failure to install the hook.
+ */
+ hook->destructor = NULL;
+ }
ao2_ref(hook, -1);
return res;
@@ -4939,6 +4957,15 @@ int ast_bridge_join_hook(struct ast_bridge_features *features,
/* Once done we put it in the container. */
res = ao2_link(features->join_hooks, hook) ? 0 : -1;
+ if (res) {
+ /*
+ * Could not link the hook into the container.
+ *
+ * Remove the hook_pvt destructor call from the hook since we
+ * are returning failure to install the hook.
+ */
+ hook->destructor = NULL;
+ }
ao2_ref(hook, -1);
return res;
@@ -4962,6 +4989,15 @@ int ast_bridge_leave_hook(struct ast_bridge_features *features,
/* Once done we put it in the container. */
res = ao2_link(features->leave_hooks, hook) ? 0 : -1;
+ if (res) {
+ /*
+ * Could not link the hook into the container.
+ *
+ * Remove the hook_pvt destructor call from the hook since we
+ * are returning failure to install the hook.
+ */
+ hook->destructor = NULL;
+ }
ao2_ref(hook, -1);
return res;
@@ -5013,11 +5049,17 @@ int ast_bridge_interval_hook(struct ast_bridge_features *features,
hook, hook->parms.timer.interval, features);
ast_heap_wrlock(features->interval_hooks);
res = ast_heap_push(features->interval_hooks, hook);
+ ast_heap_unlock(features->interval_hooks);
if (res) {
- /* Could not push the hook onto the heap. */
+ /*
+ * Could not push the hook into the heap
+ *
+ * Remove the hook_pvt destructor call from the hook since we
+ * are returning failure to install the hook.
+ */
+ hook->destructor = NULL;
ao2_ref(hook, -1);
}
- ast_heap_unlock(features->interval_hooks);
return res ? -1 : 0;
}
diff --git a/main/features.c b/main/features.c
index c44520c53..ff68b06e5 100644
--- a/main/features.c
+++ b/main/features.c
@@ -3415,6 +3415,7 @@ static int dynamic_dtmf_hook_add(struct ast_bridge_features *features, unsigned
size_t len_moh = ast_strlen_zero(moh_class) ? 0 : strlen(moh_class) + 1;
size_t len_feature = strlen(feature_name) + 1;
size_t len_data = sizeof(*hook_data) + len_name + len_args + len_moh + len_feature;
+ int res;
/* Fill in application run hook data. */
hook_data = ast_malloc(len_data);
@@ -3434,8 +3435,12 @@ static int dynamic_dtmf_hook_add(struct ast_bridge_features *features, unsigned
}
strcpy(&hook_data->app_name[hook_data->feature_offset], feature_name);/* Safe */
- return ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
+ res = ast_bridge_dtmf_hook(features, dtmf, dynamic_dtmf_hook_trip, hook_data,
ast_free_ptr, AST_BRIDGE_HOOK_REMOVE_ON_PULL);
+ if (res) {
+ ast_free(hook_data);
+ }
+ return res;
}
static int setup_dynamic_feature(void *obj, void *arg, void *data, int flags)
diff --git a/res/parking/parking_bridge_features.c b/res/parking/parking_bridge_features.c
index 8e5d739e1..3c0120762 100644
--- a/res/parking/parking_bridge_features.c
+++ b/res/parking/parking_bridge_features.c
@@ -542,6 +542,7 @@ void parking_set_duration(struct ast_bridge_features *features, struct parked_us
if (ast_bridge_interval_hook(features, time_limit,
parking_duration_callback, user, parking_duration_cb_destroyer, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
ast_log(LOG_ERROR, "Failed to apply duration limits to the parking call.\n");
+ ao2_ref(user, -1);
}
}