mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 11:58:52 +00:00
Add inheritance support to FEATURE()/FEATUREMAP().
The settings saved on the channel for FEATURE()/FEATUREMAP() were only for that channel. This patch adds the ability to have these settings inherited to child channels if you set FEATURE(inherit)=yes. Closes issue ASTERISK-21306. Review: https://reviewboard.asterisk.org/r/2415/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@385088 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -438,6 +438,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
<para>The allowed values are:</para>
|
||||
<enumlist>
|
||||
<enum name="parkingtime"><para>Specified in seconds.</para></enum>
|
||||
<enum name="inherit"><para>Inherit feature settings made in FEATURE or FEATUREMAP to child channels.</para></enum>
|
||||
</enumlist>
|
||||
</parameter>
|
||||
</syntax>
|
||||
@@ -3333,28 +3334,14 @@ struct feature_ds {
|
||||
* \todo XXX This isn't pretty. At some point it would be nice to have all
|
||||
* of the global / [general] options in a config object that we store here
|
||||
* instead of handling each one manually.
|
||||
*
|
||||
* \note If anything gets added here, don't forget to update
|
||||
* feature_ds_duplicate, as well.
|
||||
* */
|
||||
unsigned int parkingtime;
|
||||
unsigned int parkingtime_is_set:1;
|
||||
};
|
||||
|
||||
static void feature_ds_destroy(void *data)
|
||||
{
|
||||
struct feature_ds *feature_ds = data;
|
||||
|
||||
if (feature_ds->feature_map) {
|
||||
ao2_ref(feature_ds->feature_map, -1);
|
||||
feature_ds->feature_map = NULL;
|
||||
}
|
||||
|
||||
ast_free(feature_ds);
|
||||
}
|
||||
|
||||
static const struct ast_datastore_info feature_ds_info = {
|
||||
.type = "FEATURE",
|
||||
.destroy = feature_ds_destroy,
|
||||
};
|
||||
|
||||
static int feature_exten_hash(const void *obj, int flags)
|
||||
{
|
||||
const struct feature_exten *fe = obj;
|
||||
@@ -3372,6 +3359,44 @@ static int feature_exten_cmp(void *obj, void *arg, int flags)
|
||||
CMP_MATCH | CMP_STOP : 0;
|
||||
}
|
||||
|
||||
static void feature_ds_destroy(void *data)
|
||||
{
|
||||
struct feature_ds *feature_ds = data;
|
||||
|
||||
if (feature_ds->feature_map) {
|
||||
ao2_ref(feature_ds->feature_map, -1);
|
||||
feature_ds->feature_map = NULL;
|
||||
}
|
||||
|
||||
ast_free(feature_ds);
|
||||
}
|
||||
|
||||
static void *feature_ds_duplicate(void *data)
|
||||
{
|
||||
struct feature_ds *old_ds = data;
|
||||
struct feature_ds *new_ds;
|
||||
|
||||
if (!(new_ds = ast_calloc(1, sizeof(*new_ds)))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (old_ds->feature_map) {
|
||||
ao2_ref(old_ds->feature_map, +1);
|
||||
new_ds->feature_map = old_ds->feature_map;
|
||||
}
|
||||
|
||||
new_ds->parkingtime = old_ds->parkingtime;
|
||||
new_ds->parkingtime_is_set = old_ds->parkingtime_is_set;
|
||||
|
||||
return new_ds;
|
||||
}
|
||||
|
||||
static const struct ast_datastore_info feature_ds_info = {
|
||||
.type = "FEATURE",
|
||||
.destroy = feature_ds_destroy,
|
||||
.duplicate = feature_ds_duplicate,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Find or create feature datastore on a channel
|
||||
@@ -3411,6 +3436,19 @@ static struct feature_ds *get_feature_ds(struct ast_channel *chan)
|
||||
return feature_ds;
|
||||
}
|
||||
|
||||
static struct ast_datastore *get_feature_chan_ds(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_datastore *ds;
|
||||
|
||||
if (!(ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL))) {
|
||||
/* Hasn't been created yet. Trigger creation. */
|
||||
get_feature_ds(chan);
|
||||
ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL);
|
||||
}
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Get the extension for a given builtin feature
|
||||
@@ -8964,6 +9002,16 @@ static int feature_read(struct ast_channel *chan, const char *cmd, char *data,
|
||||
|
||||
if (!strcasecmp(data, "parkingtime")) {
|
||||
snprintf(buf, len, "%u", get_parkingtime(chan, NULL) / 1000);
|
||||
} else if (!strcasecmp(data, "inherit")) {
|
||||
struct ast_datastore *ds;
|
||||
unsigned int inherit;
|
||||
|
||||
ast_channel_lock(chan);
|
||||
ds = get_feature_chan_ds(chan);
|
||||
inherit = ds ? ds->inheritance : 0;
|
||||
ast_channel_unlock(chan);
|
||||
|
||||
snprintf(buf, len, "%s", inherit ? "yes" : "no");
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
|
||||
res = -1;
|
||||
@@ -8994,6 +9042,11 @@ static int feature_write(struct ast_channel *chan, const char *cmd, char *data,
|
||||
feature_ds->parkingtime_is_set = 0;
|
||||
res = -1;
|
||||
}
|
||||
} else if (!strcasecmp(data, "inherit")) {
|
||||
struct ast_datastore *ds;
|
||||
if ((ds = get_feature_chan_ds(chan))) {
|
||||
ds->inheritance = ast_true(value) ? DATASTORE_INHERIT_FOREVER : 0;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
|
||||
res = -1;
|
||||
|
Reference in New Issue
Block a user