Expand datastores to add the notion of inheritance. This will be needed for
authorTilghman Lesher <tilghman@meg.abyt.es>
Sat, 3 Mar 2007 14:40:18 +0000 (14:40 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Sat, 3 Mar 2007 14:40:18 +0000 (14:40 +0000)
the conversion of IAX2 variables from the current custom method to ast_storage.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@57691 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/channel.h
main/channel.c

index 55596b1..1f7f393 100644 (file)
@@ -153,7 +153,9 @@ extern "C" {
 #include "asterisk/linkedlists.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/compiler.h"
+#include <limits.h>
 
+#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);
 
index 3a3656c..eb59400 100644 (file)
@@ -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);  
        }