[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