[asterisk-commits] mmichelson: branch mmichelson/features_config r390020 - /team/mmichelson/feat...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed May 29 09:34:13 CDT 2013
Author: mmichelson
Date: Wed May 29 09:34:09 2013
New Revision: 390020
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=390020
Log:
Remove unnecessary config-related code from features.c
This may be my favorite commit I've made in quite a long time.
This strips out a BUNCH of code that is used by configuration in features.c
that is no longer necessary. Either
1) It's now handled in features_config.[hc]
2) It's handled in parking code.
One pseudo-exception is that I simply commented out the code that runs
dynamic features since I don't believe that an equivalent has been written
in the bridging framework yet.
I also made some notes about thread-safety in some dead code.
Modified:
team/mmichelson/features_config/main/features.c
Modified: team/mmichelson/features_config/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config/main/features.c?view=diff&rev=390020&r1=390019&r2=390020
==============================================================================
--- team/mmichelson/features_config/main/features.c (original)
+++ team/mmichelson/features_config/main/features.c Wed May 29 09:34:09 2013
@@ -599,9 +599,10 @@
static struct ast_parkinglot *default_parkinglot;
/*! Force a config reload to reload regardless of config file timestamp. */
+#ifdef TEST_FRAMEWORK
static int force_reload_load;
-
-static int parkedplay = 0; /*!< Who to play courtesytone to when someone picks up a parked call. */
+#endif
+
static int parkeddynamic = 0; /*!< Enable creation of parkinglots dynamically */
static char courtesytone[256]; /*!< Courtesy tone used to pickup parked calls and on-touch-record */
@@ -2347,6 +2348,10 @@
xfer_cfg = ast_get_chan_features_xfer_config(transferer);
ast_channel_unlock(transferer);
+ /* XXX All accesses to xfer_cfg after this point are not thread-safe,
+ * but I don't care because this is dead code
+ */
+
res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, xfer_cfg->transferdigittimeout);
if (res < 0) { /* hangup or error, (would be 0 for invalid and 1 for valid) */
finishup(transferee);
@@ -2526,6 +2531,10 @@
ast_channel_lock(transferer);
xfer_cfg = ast_get_chan_features_xfer_config(transferer);
ast_channel_unlock(transferer);
+
+ /* XXX All accesses to the xfer_cfg structure after this point are not thread-safe,
+ * but I don't care because this is dead code.
+ */
/* this is specific of atxfer */
res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, xfer_cfg->transferdigittimeout);
@@ -2968,72 +2977,6 @@
ast_verb(2, "Registered Feature '%s'\n",feature->sname);
}
-/*!
- * \brief Add new feature group
- * \param fgname feature group name.
- *
- * Add new feature group to the feature group list insert at head of list.
- * \note This function MUST be called while feature_groups is locked.
- */
-static struct feature_group *register_group(const char *fgname)
-{
- struct feature_group *fg;
-
- if (!fgname) {
- ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
- return NULL;
- }
-
- if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
- return NULL;
- }
-
- ast_string_field_set(fg, gname, fgname);
-
- AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
-
- ast_verb(2, "Registered group '%s'\n", fg->gname);
-
- return fg;
-}
-
-/*!
- * \brief Add feature to group
- * \param fg feature group
- * \param exten
- * \param feature feature to add.
- *
- * Check fg and feature specified, add feature to list
- * \note This function MUST be called while feature_groups is locked.
- */
-static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
-{
- struct feature_group_exten *fge;
-
- if (!fg) {
- ast_log(LOG_NOTICE, "You didn't pass a group!\n");
- return;
- }
-
- if (!feature) {
- ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
- return;
- }
-
- if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
- return;
- }
-
- ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
-
- fge->feature = feature;
-
- AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
-
- ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
- feature->sname, fg->gname, fge->exten);
-}
-
void ast_unregister_feature(struct ast_call_feature *feature)
{
if (!feature) {
@@ -3045,18 +2988,6 @@
ast_unlock_call_features();
ast_free(feature);
-}
-
-/*! \brief Remove all features in the list */
-static void ast_unregister_features(void)
-{
- struct ast_call_feature *feature;
-
- ast_wrlock_call_features();
- while ((feature = AST_LIST_REMOVE_HEAD(&feature_list, feature_entry))) {
- ast_free(feature);
- }
- ast_unlock_call_features();
}
/*!
@@ -3075,25 +3006,6 @@
}
return tmp;
-}
-
-/*! \brief Remove all feature groups in the list */
-static void ast_unregister_groups(void)
-{
- struct feature_group *fg;
- struct feature_group_exten *fge;
-
- AST_RWLIST_WRLOCK(&feature_groups);
- while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
- while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
- ast_string_field_free_memory(fge);
- ast_free(fge);
- }
-
- ast_string_field_free_memory(fg);
- ast_free(fg);
- }
- AST_RWLIST_UNLOCK(&feature_groups);
}
/*!
@@ -3146,6 +3058,7 @@
return ast_get_builtin_feature(chan, feature_name, buf, len);
}
+#if 0
/*!
* \brief exec an app by feature
* \param chan,peer,config,code,sense,data
@@ -3217,34 +3130,7 @@
}
return AST_FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
}
-
-static void unmap_features(void)
-{
- int x;
-
- ast_wrlock_call_features();
- for (x = 0; x < FEATURES_COUNT; x++)
- strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
- ast_unlock_call_features();
-}
-
-static int remap_feature(const char *name, const char *value)
-{
- int x, res = -1;
-
- ast_wrlock_call_features();
- for (x = 0; x < FEATURES_COUNT; x++) {
- if (strcasecmp(builtin_features[x].sname, name))
- continue;
-
- ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
- res = 0;
- break;
- }
- ast_unlock_call_features();
-
- return res;
-}
+#endif
/*!
* \brief Helper function for feature_interpret and ast_feature_detect
@@ -5023,130 +4909,6 @@
/*!
* \internal
- * \brief Set parking lot feature flag configuration value.
- *
- * \param pl_name Parking lot name for diagnostic messages.
- * \param param Parameter value to set.
- * \param var Current configuration variable item.
- *
- * \return Nothing
- */
-static void parkinglot_feature_flag_cfg(const char *pl_name, int *param, struct ast_variable *var)
-{
- ast_debug(1, "Setting parking lot %s %s to %s\n", pl_name, var->name, var->value);
- if (!strcasecmp(var->value, "both")) {
- *param = AST_FEATURE_FLAG_BYBOTH;
- } else if (!strcasecmp(var->value, "caller")) {
- *param = AST_FEATURE_FLAG_BYCALLER;
- } else if (!strcasecmp(var->value, "callee")) {
- *param = AST_FEATURE_FLAG_BYCALLEE;
- }
-}
-
-/*!
- * \internal
- * \brief Read parking lot configuration.
- *
- * \param pl_name Parking lot name for diagnostic messages.
- * \param cfg Parking lot config to update that is already initialized with defaults.
- * \param var Config variable list.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int parkinglot_config_read(const char *pl_name, struct parkinglot_cfg *cfg, struct ast_variable *var)
-{
- int error = 0;
-
- while (var) {
- if (!strcasecmp(var->name, "context")) {
- ast_copy_string(cfg->parking_con, var->value, sizeof(cfg->parking_con));
- } else if (!strcasecmp(var->name, "parkext")) {
- ast_copy_string(cfg->parkext, var->value, sizeof(cfg->parkext));
- } else if (!strcasecmp(var->name, "parkext_exclusive")) {
- cfg->parkext_exclusive = ast_true(var->value);
- } else if (!strcasecmp(var->name, "parkinghints")) {
- cfg->parkaddhints = ast_true(var->value);
- } else if (!strcasecmp(var->name, "parkedmusicclass")) {
- ast_copy_string(cfg->mohclass, var->value, sizeof(cfg->mohclass));
- } else if (!strcasecmp(var->name, "parkingtime")) {
- unsigned int parkingtime = 0;
-
- if ((sscanf(var->value, "%30u", &parkingtime) != 1) || parkingtime < 1) {
- ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
- error = -1;
- } else {
- cfg->parkingtime = parkingtime * 1000;
- }
- } else if (!strcasecmp(var->name, "parkpos")) {
- int start = 0;
- int end = 0;
-
- if (sscanf(var->value, "%30d-%30d", &start, &end) != 2) {
- ast_log(LOG_WARNING,
- "Format for parking positions is a-b, where a and b are numbers at line %d of %s\n",
- var->lineno, var->file);
- error = -1;
- } else if (end < start || start <= 0 || end <= 0) {
- ast_log(LOG_WARNING, "Parking range is invalid. Must be a <= b, at line %d of %s\n",
- var->lineno, var->file);
- error = -1;
- } else {
- cfg->parking_start = start;
- cfg->parking_stop = end;
- }
- } else if (!strcasecmp(var->name, "findslot")) {
- cfg->parkfindnext = (!strcasecmp(var->value, "next"));
- } else if (!strcasecmp(var->name, "parkedcalltransfers")) {
- parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcalltransfers, var);
- } else if (!strcasecmp(var->name, "parkedcallreparking")) {
- parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallreparking, var);
- } else if (!strcasecmp(var->name, "parkedcallhangup")) {
- parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallhangup, var);
- } else if (!strcasecmp(var->name, "parkedcallrecording")) {
- parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallrecording, var);
- } else if (!strcasecmp(var->name, "comebackcontext")) {
- ast_copy_string(cfg->comebackcontext, var->value, sizeof(cfg->comebackcontext));
- } else if (!strcasecmp(var->name, "comebacktoorigin")) {
- cfg->comebacktoorigin = ast_true(var->value);
- } else if (!strcasecmp(var->name, "comebackdialtime")) {
- if ((sscanf(var->value, "%30u", &cfg->comebackdialtime) != 1)
- || (cfg->comebackdialtime < 1)) {
- ast_log(LOG_WARNING, "%s is not a valid comebackdialtime\n", var->value);
- cfg->parkingtime = DEFAULT_COMEBACK_DIAL_TIME;
- }
- }
- var = var->next;
- }
-
- /* Check for configuration errors */
- if (ast_strlen_zero(cfg->parking_con)) {
- ast_log(LOG_WARNING, "Parking lot %s needs context\n", pl_name);
- error = -1;
- }
- if (ast_strlen_zero(cfg->parkext)) {
- ast_log(LOG_WARNING, "Parking lot %s needs parkext\n", pl_name);
- error = -1;
- }
- if (!cfg->parking_start) {
- ast_log(LOG_WARNING, "Parking lot %s needs parkpos\n", pl_name);
- error = -1;
- }
- if (!cfg->comebacktoorigin && ast_strlen_zero(cfg->comebackcontext)) {
- ast_log(LOG_WARNING, "Parking lot %s has comebacktoorigin set false"
- "but has no comebackcontext.\n",
- pl_name);
- error = -1;
- }
- if (error) {
- cfg->is_invalid = 1;
- }
-
- return error;
-}
-
-/*!
- * \internal
* \brief Activate the given parkinglot.
*
* \param parkinglot Parking lot to activate.
@@ -5206,1048 +4968,6 @@
return disabled ? -1 : 0;
}
-/*! \brief Build parkinglot from configuration and chain it in if it doesn't already exist */
-static struct ast_parkinglot *build_parkinglot(const char *pl_name, struct ast_variable *var)
-{
- struct ast_parkinglot *parkinglot;
- const struct parkinglot_cfg *cfg_defaults;
- struct parkinglot_cfg new_cfg;
- int cfg_error;
- int oldparkinglot = 0;
-
- parkinglot = find_parkinglot(pl_name);
- if (parkinglot) {
- oldparkinglot = 1;
- } else {
- parkinglot = create_parkinglot(pl_name);
- if (!parkinglot) {
- return NULL;
- }
- }
- if (!strcmp(parkinglot->name, DEFAULT_PARKINGLOT)) {
- cfg_defaults = &parkinglot_cfg_default_default;
- } else {
- cfg_defaults = &parkinglot_cfg_default;
- }
- new_cfg = *cfg_defaults;
-
- ast_debug(1, "Building parking lot %s\n", parkinglot->name);
-
- ao2_lock(parkinglot);
-
- /* Do some config stuff */
- cfg_error = parkinglot_config_read(parkinglot->name, &new_cfg, var);
- if (oldparkinglot) {
- if (cfg_error) {
- /* Bad configuration read. Keep using the original config. */
- ast_log(LOG_WARNING, "Changes to parking lot %s are discarded.\n",
- parkinglot->name);
- cfg_error = 0;
- } else if (!AST_LIST_EMPTY(&parkinglot->parkings)
- && memcmp(&new_cfg, &parkinglot->cfg, sizeof(parkinglot->cfg))) {
- /* Try reloading later when parking lot is empty. */
- ast_log(LOG_WARNING,
- "Parking lot %s has parked calls. Parking lot changes discarded.\n",
- parkinglot->name);
- force_reload_load = 1;
- } else {
- /* Accept the new config */
- parkinglot->cfg = new_cfg;
- }
- } else {
- /* Load the initial parking lot config. */
- parkinglot->cfg = new_cfg;
- }
- parkinglot->the_mark = 0;
-
- ao2_unlock(parkinglot);
-
- if (cfg_error) {
- /* Only new parking lots could have config errors here. */
- ast_log(LOG_WARNING, "New parking lot %s is discarded.\n", parkinglot->name);
- parkinglot_unref(parkinglot);
- return NULL;
- }
-
- /* Move it into the list, if it wasn't already there */
- if (!oldparkinglot) {
- ao2_link(parkinglots, parkinglot);
- }
- parkinglot_unref(parkinglot);
-
- return parkinglot;
-}
-
-/*!
- * \internal
- * \brief Process an applicationmap section config line.
- *
- * \param var Config variable line.
- *
- * \return Nothing
- */
-static void process_applicationmap_line(struct ast_variable *var)
-{
- char *tmp_val = ast_strdupa(var->value);
- char *activateon, *new_syn;
- struct ast_call_feature *feature;
- AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(exten);
- AST_APP_ARG(activatedby);
- AST_APP_ARG(app);
- AST_APP_ARG(app_args);
- AST_APP_ARG(moh_class);
- );
-
- AST_STANDARD_APP_ARGS(args, tmp_val);
- if ((new_syn = strchr(args.app, '('))) {
- /* New syntax */
- args.moh_class = args.app_args;
- args.app_args = new_syn;
- *args.app_args++ = '\0';
- if (args.app_args[strlen(args.app_args) - 1] == ')') {
- args.app_args[strlen(args.app_args) - 1] = '\0';
- }
- }
-
- activateon = strsep(&args.activatedby, "/");
-
- /*! \todo XXX var_name or app_args ? */
- if (ast_strlen_zero(args.app)
- || ast_strlen_zero(args.exten)
- || ast_strlen_zero(activateon)
- || ast_strlen_zero(var->name)) {
- ast_log(LOG_NOTICE,
- "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
- args.app, args.exten, activateon, var->name);
- return;
- }
-
- ast_rdlock_call_features();
- if (find_dynamic_feature(var->name)) {
- ast_unlock_call_features();
- ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n",
- var->name);
- return;
- }
- ast_unlock_call_features();
-
- if (!(feature = ast_calloc(1, sizeof(*feature)))) {
- return;
- }
-
- ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
- ast_copy_string(feature->app, args.app, FEATURE_APP_LEN);
- ast_copy_string(feature->exten, args.exten, FEATURE_EXTEN_LEN);
-
- if (args.app_args) {
- ast_copy_string(feature->app_args, args.app_args, FEATURE_APP_ARGS_LEN);
- }
-
- if (args.moh_class) {
- ast_copy_string(feature->moh_class, args.moh_class, FEATURE_MOH_LEN);
- }
-
- ast_copy_string(feature->exten, args.exten, sizeof(feature->exten));
- feature->operation = feature_exec_app;
- ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
-
- /* Allow caller and callee to be specified for backwards compatability */
- if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller")) {
- ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
- } else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee")) {
- ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
- } else {
- ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
- " must be 'self', or 'peer'\n", var->name);
- ast_free(feature);
- return;
- }
-
- /*
- * We will parse and require correct syntax for the ActivatedBy
- * option, but the ActivatedBy option is not honored anymore.
- */
- if (ast_strlen_zero(args.activatedby)) {
- ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
- } else if (!strcasecmp(args.activatedby, "caller")) {
- ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
- } else if (!strcasecmp(args.activatedby, "callee")) {
- ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
- } else if (!strcasecmp(args.activatedby, "both")) {
- ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
- } else {
- ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
- " must be 'caller', or 'callee', or 'both'\n", var->name);
- ast_free(feature);
- return;
- }
-
- ast_register_feature(feature);
-
- ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n",
- var->name, args.app, args.app_args, args.exten);
-}
-
-static int process_config(struct ast_config *cfg)
-{
- int i;
- struct ast_variable *var = NULL;
- struct feature_group *fg = NULL;
- char *ctg;
- static const char * const categories[] = {
- /* Categories in features.conf that are not
- * to be parsed as group categories
- */
- "general",
- "featuremap",
- "applicationmap"
- };
-
- /* Set global call parking defaults. */
- courtesytone[0] = '\0';
- parkedplay = 0;
- adsipark = 0;
- parkeddynamic = 0;
-
- var = ast_variable_browse(cfg, "general");
- build_parkinglot(DEFAULT_PARKINGLOT, var);
- for (; var; var = var->next) {
- if (!strcasecmp(var->name, "parkeddynamic")) {
- parkeddynamic = ast_true(var->value);
- } else if (!strcasecmp(var->name, "adsipark")) {
- adsipark = ast_true(var->value);
- } else if (!strcasecmp(var->name, "courtesytone")) {
- ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
- } else if (!strcasecmp(var->name, "parkedplay")) {
- if (!strcasecmp(var->value, "both")) {
- parkedplay = 2;
- } else if (!strcasecmp(var->value, "parked")) {
- parkedplay = 1;
- } else {
- parkedplay = 0;
- }
- }
- }
-
- unmap_features();
- for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
- if (remap_feature(var->name, var->value)) {
- ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
- }
- }
-
- /* Map a key combination to an application */
- ast_unregister_features();
- for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
- process_applicationmap_line(var);
- }
-
- ast_unregister_groups();
- AST_RWLIST_WRLOCK(&feature_groups);
-
- ctg = NULL;
- while ((ctg = ast_category_browse(cfg, ctg))) {
- /* Is this a parkinglot definition ? */
- if (!strncasecmp(ctg, "parkinglot_", strlen("parkinglot_"))) {
- ast_debug(2, "Found configuration section %s, assume parking context\n", ctg);
- if (!build_parkinglot(ctg, ast_variable_browse(cfg, ctg))) {
- ast_log(LOG_ERROR, "Could not build parking lot %s. Configuration error.\n", ctg);
- } else {
- ast_debug(1, "Configured parking context %s\n", ctg);
- }
- continue;
- }
-
- /* No, check if it's a group */
- for (i = 0; i < ARRAY_LEN(categories); i++) {
- if (!strcasecmp(categories[i], ctg)) {
- break;
- }
- }
- if (i < ARRAY_LEN(categories)) {
- continue;
- }
-
- if (!(fg = register_group(ctg))) {
- continue;
- }
-
- for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
- struct ast_call_feature *feature;
-
- ast_rdlock_call_features();
- feature = ast_find_call_feature(var->name);
- ast_unlock_call_features();
- if (!feature) {
- ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
- continue;
- }
-
- register_group_feature(fg, var->value, feature);
- }
- }
-
- AST_RWLIST_UNLOCK(&feature_groups);
-
- return 0;
-}
-
-/*!
- * \internal
- * \brief Destroy the given dialplan usage context.
- *
- * \param doomed Parking lot usage context to destroy.
- *
- * \return Nothing
- */
-static void destroy_dialplan_usage_context(struct parking_dp_context *doomed)
-{
- struct parking_dp_ramp *ramp;
- struct parking_dp_spaces *spaces;
-
- while ((ramp = AST_LIST_REMOVE_HEAD(&doomed->access_extens, node))) {
- ast_free(ramp);
- }
- while ((spaces = AST_LIST_REMOVE_HEAD(&doomed->spaces, node))) {
- ast_free(spaces);
- }
- while ((spaces = AST_LIST_REMOVE_HEAD(&doomed->hints, node))) {
- ast_free(spaces);
- }
- ast_free(doomed);
-}
-
-/*!
- * \internal
- * \brief Destroy the given dialplan usage map.
- *
- * \param doomed Parking lot usage map to destroy.
- *
- * \return Nothing
- */
-static void destroy_dialplan_usage_map(struct parking_dp_map *doomed)
-{
- struct parking_dp_context *item;
-
- while ((item = AST_LIST_REMOVE_HEAD(doomed, node))) {
- destroy_dialplan_usage_context(item);
- }
-}
-
-/*!
- * \internal
- * \brief Create a new parking lot ramp dialplan usage node.
- *
- * \param exten Parking lot access ramp extension.
- * \param exclusive TRUE if the parking lot access ramp extension is exclusive.
- *
- * \retval New usage ramp node on success.
- * \retval NULL on error.
- */
-static struct parking_dp_ramp *build_dialplan_useage_ramp(const char *exten, int exclusive)
-{
- struct parking_dp_ramp *ramp_node;
-
- ramp_node = ast_calloc(1, sizeof(*ramp_node) + strlen(exten));
- if (!ramp_node) {
- return NULL;
- }
- ramp_node->exclusive = exclusive;
- strcpy(ramp_node->exten, exten);
- return ramp_node;
-}
-
-/*!
- * \internal
- * \brief Add parking lot access ramp to the context ramp usage map.
- *
- * \param ramp_map Current parking lot context ramp usage map.
- * \param exten Parking lot access ramp extension to add.
- * \param exclusive TRUE if the parking lot access ramp extension is exclusive.
- * \param lot Parking lot supplying reference data.
- * \param complain TRUE if to complain of parking lot ramp conflicts.
- *
- * \retval 0 on success. The ramp_map is updated.
- * \retval -1 on failure.
- */
-static int usage_context_add_ramp(struct parking_dp_ramp_map *ramp_map, const char *exten, int exclusive, struct ast_parkinglot *lot, int complain)
-{
- struct parking_dp_ramp *cur_ramp;
- struct parking_dp_ramp *new_ramp;
- int cmp;
-
- /* Make sure that exclusive is only 0 or 1 */
- if (exclusive) {
- exclusive = 1;
- }
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(ramp_map, cur_ramp, node) {
- cmp = strcmp(exten, cur_ramp->exten);
- if (cmp > 0) {
- /* The parking lot ramp goes after this node. */
- continue;
- }
- if (cmp == 0) {
- /* The ramp is already in the map. */
- if (complain && (cur_ramp->exclusive || exclusive)) {
- ast_log(LOG_WARNING,
- "Parking lot '%s' parkext %s@%s used by another parking lot.\n",
- lot->name, exten, lot->cfg.parking_con);
- }
- return 0;
- }
- /* The new parking lot ramp goes before this node. */
- new_ramp = build_dialplan_useage_ramp(exten, exclusive);
- if (!new_ramp) {
- return -1;
- }
- AST_LIST_INSERT_BEFORE_CURRENT(new_ramp, node);
- return 0;
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- /* New parking lot access ramp goes on the end. */
- new_ramp = build_dialplan_useage_ramp(exten, exclusive);
- if (!new_ramp) {
- return -1;
- }
- AST_LIST_INSERT_TAIL(ramp_map, new_ramp, node);
- return 0;
-}
-
-/*!
- * \internal
- * \brief Create a new parking lot spaces dialplan usage node.
- *
- * \param start First parking lot space to add.
- * \param stop Last parking lot space to add.
- *
- * \retval New usage ramp node on success.
- * \retval NULL on error.
- */
-static struct parking_dp_spaces *build_dialplan_useage_spaces(int start, int stop)
-{
- struct parking_dp_spaces *spaces_node;
-
- spaces_node = ast_calloc(1, sizeof(*spaces_node));
- if (!spaces_node) {
- return NULL;
- }
- spaces_node->start = start;
- spaces_node->stop = stop;
- return spaces_node;
-}
-
-/*!
- * \internal
- * \brief Add parking lot spaces to the context space usage map.
- *
- * \param space_map Current parking lot context space usage map.
- * \param start First parking lot space to add.
- * \param stop Last parking lot space to add.
- * \param lot Parking lot supplying reference data.
- * \param complain TRUE if to complain of parking lot spaces conflicts.
- *
- * \retval 0 on success. The space_map is updated.
- * \retval -1 on failure.
- */
-static int usage_context_add_spaces(struct parking_dp_space_map *space_map, int start, int stop, struct ast_parkinglot *lot, int complain)
-{
- struct parking_dp_spaces *cur_node;
- struct parking_dp_spaces *expand_node;
- struct parking_dp_spaces *new_node;
-
- expand_node = NULL;
- AST_LIST_TRAVERSE_SAFE_BEGIN(space_map, cur_node, node) {
- /* NOTE: stop + 1 to combine immediately adjacent nodes into one. */
- if (expand_node) {
- /* The previous node is expanding to possibly eat following nodes. */
- if (expand_node->stop + 1 < cur_node->start) {
- /* Current node is completely after expanding node. */
- return 0;
- }
-
- if (complain
- && ((cur_node->start <= start && start <= cur_node->stop)
- || (cur_node->start <= stop && stop <= cur_node->stop)
- || (start < cur_node->start && cur_node->stop < stop))) {
- /* Only complain once per range add. */
- complain = 0;
- ast_log(LOG_WARNING,
- "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
- lot->name, start, stop, lot->cfg.parking_con);
- }
-
- /* Current node is eaten by the expanding node. */
- if (expand_node->stop < cur_node->stop) {
- expand_node->stop = cur_node->stop;
- }
- AST_LIST_REMOVE_CURRENT(node);
- ast_free(cur_node);
- continue;
- }
-
- if (cur_node->stop + 1 < start) {
- /* New range is completely after current node. */
- continue;
- }
- if (stop + 1 < cur_node->start) {
- /* New range is completely before current node. */
- new_node = build_dialplan_useage_spaces(start, stop);
- if (!new_node) {
- return -1;
- }
- AST_LIST_INSERT_BEFORE_CURRENT(new_node, node);
- return 0;
- }
-
- if (complain
- && ((cur_node->start <= start && start <= cur_node->stop)
- || (cur_node->start <= stop && stop <= cur_node->stop)
- || (start < cur_node->start && cur_node->stop < stop))) {
- /* Only complain once per range add. */
- complain = 0;
- ast_log(LOG_WARNING,
- "Parking lot '%s' parkpos %d-%d@%s overlaps another parking lot.\n",
- lot->name, start, stop, lot->cfg.parking_con);
- }
-
- /* Current node range overlaps or is immediately adjacent to new range. */
- if (start < cur_node->start) {
- /* Expand the current node in the front. */
- cur_node->start = start;
- }
- if (stop <= cur_node->stop) {
- /* Current node is not expanding in the rear. */
- return 0;
- }
- cur_node->stop = stop;
- expand_node = cur_node;
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- if (expand_node) {
- /*
- * The previous node expanded and either ate all following nodes
- * or it was the last node.
- */
- return 0;
- }
-
- /* New range goes on the end. */
- new_node = build_dialplan_useage_spaces(start, stop);
- if (!new_node) {
- return -1;
- }
- AST_LIST_INSERT_TAIL(space_map, new_node, node);
- return 0;
-}
-
-/*!
- * \internal
- * \brief Add parking lot spaces to the context dialplan usage node.
- *
- * \param ctx_node Usage node to add parking lot spaces.
- * \param lot Parking lot to add data to ctx_node.
- * \param complain TRUE if to complain of parking lot ramp and spaces conflicts.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int dialplan_usage_add_parkinglot_data(struct parking_dp_context *ctx_node, struct ast_parkinglot *lot, int complain)
-{
- if (usage_context_add_ramp(&ctx_node->access_extens, lot->cfg.parkext,
- lot->cfg.parkext_exclusive, lot, complain)) {
- return -1;
- }
- if (usage_context_add_spaces(&ctx_node->spaces, lot->cfg.parking_start,
- lot->cfg.parking_stop, lot, complain)) {
- return -1;
- }
- if (lot->cfg.parkaddhints
- && usage_context_add_spaces(&ctx_node->hints, lot->cfg.parking_start,
- lot->cfg.parking_stop, lot, 0)) {
- return -1;
- }
- return 0;
-}
-
-/*!
- * \internal
- * \brief Create a new parking lot context dialplan usage node.
- *
- * \param lot Parking lot to create a new dialplan usage from.
- *
- * \retval New usage context node on success.
- * \retval NULL on error.
- */
-static struct parking_dp_context *build_dialplan_useage_context(struct ast_parkinglot *lot)
-{
- struct parking_dp_context *ctx_node;
-
- ctx_node = ast_calloc(1, sizeof(*ctx_node) + strlen(lot->cfg.parking_con));
- if (!ctx_node) {
- return NULL;
- }
- if (dialplan_usage_add_parkinglot_data(ctx_node, lot, 0)) {
- destroy_dialplan_usage_context(ctx_node);
- return NULL;
- }
- strcpy(ctx_node->context, lot->cfg.parking_con);
- return ctx_node;
-}
-
-/*!
- * \internal
- * \brief Add the given parking lot dialplan usage to the dialplan usage map.
- *
- * \param usage_map Parking lot usage map to add the given parking lot.
- * \param lot Parking lot to add dialplan usage.
- * \param complain TRUE if to complain of parking lot ramp and spaces conflicts.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int dialplan_usage_add_parkinglot(struct parking_dp_map *usage_map, struct ast_parkinglot *lot, int complain)
-{
- struct parking_dp_context *cur_ctx;
- struct parking_dp_context *new_ctx;
- int cmp;
-
- AST_LIST_TRAVERSE_SAFE_BEGIN(usage_map, cur_ctx, node) {
- cmp = strcmp(lot->cfg.parking_con, cur_ctx->context);
- if (cmp > 0) {
- /* The parking lot context goes after this node. */
- continue;
- }
- if (cmp == 0) {
- /* This is the node we will add parking lot spaces to the map. */
- return dialplan_usage_add_parkinglot_data(cur_ctx, lot, complain);
- }
- /* The new parking lot context goes before this node. */
- new_ctx = build_dialplan_useage_context(lot);
- if (!new_ctx) {
- return -1;
- }
- AST_LIST_INSERT_BEFORE_CURRENT(new_ctx, node);
- return 0;
- }
- AST_LIST_TRAVERSE_SAFE_END;
-
- /* New parking lot context goes on the end. */
- new_ctx = build_dialplan_useage_context(lot);
- if (!new_ctx) {
- return -1;
- }
- AST_LIST_INSERT_TAIL(usage_map, new_ctx, node);
- return 0;
-}
-
-/*!
- * \internal
- * \brief Build the dialplan usage map of the current parking lot container.
- *
- * \param usage_map Parking lot usage map. Must already be initialized.
- * \param complain TRUE if to complain of parking lot ramp and spaces conflicts.
- *
- * \retval 0 on success. The usage_map is filled in.
- * \retval -1 on failure. Built usage_map is incomplete.
- */
-static int build_dialplan_useage_map(struct parking_dp_map *usage_map, int complain)
-{
- int status = 0;
- struct ao2_iterator iter;
- struct ast_parkinglot *curlot;
-
- /* For all parking lots */
- iter = ao2_iterator_init(parkinglots, 0);
- for (; (curlot = ao2_iterator_next(&iter)); ao2_ref(curlot, -1)) {
- /* Add the parking lot to the map. */
- if (dialplan_usage_add_parkinglot(usage_map, curlot, complain)) {
- ao2_ref(curlot, -1);
- status = -1;
- break;
- }
- }
- ao2_iterator_destroy(&iter);
-
- return status;
-}
-
-/*!
- * \internal
- * \brief Remove the given extension if it exists.
- *
- * \param context Dialplan database context name.
- * \param exten Extension to remove.
- * \param priority Extension priority to remove.
- *
- * \return Nothing
- */
-static void remove_exten_if_exist(const char *context, const char *exten, int priority)
-{
- struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
-
- if (pbx_find_extension(NULL, NULL, &q, context, exten, priority, NULL, NULL,
- E_MATCH)) {
- ast_debug(1, "Removing unneeded parking lot exten: %s@%s priority:%d\n",
- context, exten, priority);
- ast_context_remove_extension(context, exten, priority, registrar);
- }
-}
-
-/*!
- * \internal
- * \brief Remove unused parking lot access ramp items.
- *
- * \param context Dialplan database context name.
- * \param old_ramps Before configuration reload access ramp usage map.
- * \param new_ramps After configuration reload access ramp usage map.
- *
- * \details
- * Remove access ramp items that were in the old context but not in the
- * new context.
- *
- * \return Nothing
- */
-static void remove_dead_ramp_usage(const char *context, struct parking_dp_ramp_map *old_ramps, struct parking_dp_ramp_map *new_ramps)
-{
- struct parking_dp_ramp *old_ramp;
- struct parking_dp_ramp *new_ramp;
- int cmp;
-
- old_ramp = AST_LIST_FIRST(old_ramps);
- new_ramp = AST_LIST_FIRST(new_ramps);
-
- while (new_ramp) {
- if (!old_ramp) {
- /* No old ramps left, so no dead ramps can remain. */
- return;
- }
- cmp = strcmp(old_ramp->exten, new_ramp->exten);
- if (cmp < 0) {
- /* New map does not have old ramp. */
- remove_exten_if_exist(context, old_ramp->exten, 1);
- old_ramp = AST_LIST_NEXT(old_ramp, node);
- continue;
- }
- if (cmp == 0) {
- /* Old and new map have this ramp. */
- old_ramp = AST_LIST_NEXT(old_ramp, node);
- } else {
- /* Old map does not have new ramp. */
- }
- new_ramp = AST_LIST_NEXT(new_ramp, node);
- }
-
- /* Any old ramps left must be dead. */
- for (; old_ramp; old_ramp = AST_LIST_NEXT(old_ramp, node)) {
- remove_exten_if_exist(context, old_ramp->exten, 1);
- }
-}
-
-/*!
- * \internal
- * \brief Destroy the given parking space.
- *
- * \param context Dialplan database context name.
- * \param space Parking space.
- *
- * \return Nothing
- */
-static void destroy_space(const char *context, int space)
-{
- char exten[AST_MAX_EXTENSION];
-
- /* Destroy priorities of the parking space that we registered. */
- snprintf(exten, sizeof(exten), "%d", space);
- remove_exten_if_exist(context, exten, PRIORITY_HINT);
- remove_exten_if_exist(context, exten, 1);
-}
-
-/*!
- * \internal
- * \brief Remove unused parking lot space items.
- *
- * \param context Dialplan database context name.
- * \param old_spaces Before configuration reload parking space usage map.
- * \param new_spaces After configuration reload parking space usage map.
- * \param destroy_space Function to destroy parking space item.
- *
- * \details
- * Remove parking space items that were in the old context but
- * not in the new context.
- *
- * \return Nothing
- */
-static void remove_dead_spaces_usage(const char *context,
- struct parking_dp_space_map *old_spaces, struct parking_dp_space_map *new_spaces,
- void (*destroy_space)(const char *context, int space))
-{
- struct parking_dp_spaces *old_range;
- struct parking_dp_spaces *new_range;
- int space;/*!< Current position in the current old range. */
- int stop;
-
- old_range = AST_LIST_FIRST(old_spaces);
- new_range = AST_LIST_FIRST(new_spaces);
- space = -1;
-
- while (old_range) {
- if (space < old_range->start) {
- space = old_range->start;
- }
- if (new_range) {
- if (space < new_range->start) {
- /* Current position in old range starts before new range. */
- if (old_range->stop < new_range->start) {
- /* Old range ends before new range. */
- stop = old_range->stop;
- old_range = AST_LIST_NEXT(old_range, node);
- } else {
- /* Tail of old range overlaps new range. */
- stop = new_range->start - 1;
- }
- } else if (/* new_range->start <= space && */ space <= new_range->stop) {
- /* Current position in old range overlaps new range. */
- if (old_range->stop <= new_range->stop) {
- /* Old range ends at or before new range. */
- old_range = AST_LIST_NEXT(old_range, node);
- } else {
- /* Old range extends beyond end of new range. */
- space = new_range->stop + 1;
- new_range = AST_LIST_NEXT(new_range, node);
- }
- continue;
- } else /* if (new_range->stop < space) */ {
- /* Current position in old range starts after new range. */
- new_range = AST_LIST_NEXT(new_range, node);
- continue;
- }
- } else {
- /* No more new ranges. All remaining old spaces are dead. */
- stop = old_range->stop;
- old_range = AST_LIST_NEXT(old_range, node);
- }
-
- /* Destroy dead parking spaces. */
- for (; space <= stop; ++space) {
- destroy_space(context, space);
- }
- }
-}
-
-/*!
- * \internal
- * \brief Remove unused parking lot context items.
- *
- * \param context Dialplan database context name.
- * \param old_ctx Before configuration reload context usage map.
- * \param new_ctx After configuration reload context usage map.
- *
- * \details
- * Remove context usage items that were in the old context but not in the
- * new context.
- *
- * \return Nothing
- */
-static void remove_dead_context_usage(const char *context, struct parking_dp_context *old_ctx, struct parking_dp_context *new_ctx)
-{
- remove_dead_ramp_usage(context, &old_ctx->access_extens, &new_ctx->access_extens);
- remove_dead_spaces_usage(context, &old_ctx->spaces, &new_ctx->spaces, destroy_space);
-#if 0
- /* I don't think we should destroy hints if the parking space still exists. */
- remove_dead_spaces_usage(context, &old_ctx->hints, &new_ctx->hints, destroy_space_hint);
-#endif
-}
-
-/*!
- * \internal
- * \brief Remove unused parking lot dialplan items.
- *
- * \param old_map Before configuration reload dialplan usage map.
- * \param new_map After configuration reload dialplan usage map.
- *
- * \details
- * Remove dialplan items that were in the old map but not in the
- * new map.
- *
- * \return Nothing
- */
-static void remove_dead_dialplan_useage(struct parking_dp_map *old_map, struct parking_dp_map *new_map)
-{
- struct parking_dp_context *old_ctx;
- struct parking_dp_context *new_ctx;
- struct ast_context *con;
- int cmp;
-
- old_ctx = AST_LIST_FIRST(old_map);
- new_ctx = AST_LIST_FIRST(new_map);
-
- while (new_ctx) {
- if (!old_ctx) {
- /* No old contexts left, so no dead stuff can remain. */
- return;
- }
- cmp = strcmp(old_ctx->context, new_ctx->context);
- if (cmp < 0) {
- /* New map does not have old map context. */
- con = ast_context_find(old_ctx->context);
- if (con) {
- ast_context_destroy(con, registrar);
- }
- old_ctx = AST_LIST_NEXT(old_ctx, node);
- continue;
- }
- if (cmp == 0) {
- /* Old and new map have this context. */
- remove_dead_context_usage(old_ctx->context, old_ctx, new_ctx);
- old_ctx = AST_LIST_NEXT(old_ctx, node);
- } else {
- /* Old map does not have new map context. */
- }
- new_ctx = AST_LIST_NEXT(new_ctx, node);
- }
-
- /* Any old contexts left must be dead. */
- for (; old_ctx; old_ctx = AST_LIST_NEXT(old_ctx, node)) {
- con = ast_context_find(old_ctx->context);
- if (con) {
- ast_context_destroy(con, registrar);
- }
- }
-}
-
-static int parkinglot_markall_cb(void *obj, void *arg, int flags)
-{
- struct ast_parkinglot *parkinglot = obj;
-
- parkinglot->the_mark = 1;
- return 0;
-}
-
-static int parkinglot_is_marked_cb(void *obj, void *arg, int flags)
-{
- struct ast_parkinglot *parkinglot = obj;
-
- if (parkinglot->the_mark) {
- if (AST_LIST_EMPTY(&parkinglot->parkings)) {
- /* This parking lot can actually be deleted. */
- return CMP_MATCH;
- }
- /* Try reloading later when parking lot is empty. */
- ast_log(LOG_WARNING,
- "Parking lot %s has parked calls. Could not remove.\n",
- parkinglot->name);
- parkinglot->disabled = 1;
- force_reload_load = 1;
- }
-
- return 0;
-}
-
-static int parkinglot_activate_cb(void *obj, void *arg, int flags)
-{
- struct ast_parkinglot *parkinglot = obj;
-
- if (parkinglot->the_mark) {
- /*
- * Don't activate a parking lot that still bears the_mark since
- * it is effectively deleted.
- */
- return 0;
- }
-
- if (parkinglot_activate(parkinglot)) {
- /*
- * The parking lot failed to activate. Allow reloading later to
- * see if that fixes it.
- */
- force_reload_load = 1;
- ast_log(LOG_WARNING, "Parking lot %s not open for business.\n", parkinglot->name);
- } else {
- ast_debug(1, "Parking lot %s now open for business. (parkpos %d-%d)\n",
- parkinglot->name, parkinglot->cfg.parking_start,
- parkinglot->cfg.parking_stop);
- }
-
- return 0;
-}
-
-static int load_config(int reload)
-{
- struct ast_flags config_flags = {
- reload && !force_reload_load ? CONFIG_FLAG_FILEUNCHANGED : 0 };
[... 117 lines stripped ...]
More information about the asterisk-commits
mailing list