diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 55596b147d..1f7f3934a9 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -153,7 +153,9 @@ extern "C" { #include "asterisk/linkedlists.h" #include "asterisk/stringfields.h" #include "asterisk/compiler.h" +#include +#define DATASTORE_INHERIT_FOREVER INT_MAX #define AST_MAX_FDS 10 /* @@ -185,6 +187,7 @@ struct ast_generator { /*! \brief Structure for a data store type */ struct ast_datastore_info { const char *type; /*!< Type of data store */ + void *(*duplicate)(void *data); /*!< Duplicate item data (used for inheritance) */ void (*destroy)(void *data); /*!< Destroy function */ }; @@ -193,6 +196,7 @@ struct ast_datastore { char *uid; /*!< Unique data store identifier */ void *data; /*!< Contained data */ const struct ast_datastore_info *info; /*!< Data store type information */ + unsigned int inheritance; /*!< Number of levels this item will continue to be inherited */ AST_LIST_ENTRY(ast_datastore) entry; /*!< Used for easy linking */ }; @@ -608,6 +612,9 @@ struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_inf /*! \brief Free a channel datastore structure */ int ast_channel_datastore_free(struct ast_datastore *datastore); +/*! \brief Inherit datastores from a parent to a child. */ +int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to); + /*! \brief Add a datastore to a channel */ int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore); diff --git a/main/channel.c b/main/channel.c index 3a3656c35a..eb59400604 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1145,7 +1145,7 @@ int ast_channel_datastore_free(struct ast_datastore *datastore) /* Free allocated UID memory */ if (datastore->uid != NULL) { - free(datastore->uid); + ast_free(datastore->uid); datastore->uid = NULL; } @@ -1155,6 +1155,23 @@ int ast_channel_datastore_free(struct ast_datastore *datastore) return res; } +int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to) +{ + struct ast_datastore *datastore = NULL, *datastore2; + + AST_LIST_TRAVERSE(&from->datastores, datastore, entry) { + if (datastore->inheritance > 0) { + datastore2 = ast_channel_datastore_alloc(datastore->info, datastore->uid); + if (datastore2) { + datastore2->data = datastore->info->duplicate(datastore->data); + datastore2->inheritance = datastore->inheritance == DATASTORE_INHERIT_FOREVER ? DATASTORE_INHERIT_FOREVER : datastore->inheritance - 1; + AST_LIST_INSERT_TAIL(&to->datastores, datastore2, entry); + } + } + } + return 0; +} + int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore) { int res = 0; @@ -2817,8 +2834,10 @@ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *d /* XXX why is this necessary, for the parent_channel perhaps ? */ if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) ast_set_callerid(chan, oh->cid_num, oh->cid_name, oh->cid_num); - if (oh->parent_channel) + if (oh->parent_channel) { ast_channel_inherit_variables(oh->parent_channel, chan); + ast_channel_datastore_inherit(oh->parent_channel, chan); + } if (oh->account) ast_cdr_setaccount(chan, oh->account); }