]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix bad channel application data reference.
authorMark Michelson <mmichelson@digium.com>
Tue, 11 Sep 2012 15:26:10 +0000 (15:26 +0000)
committerMark Michelson <mmichelson@digium.com>
Tue, 11 Sep 2012 15:26:10 +0000 (15:26 +0000)
When channels get bridged due to an AMI bridge action
or a DTMF attended transfer, the two channels that
get bridged have their application data pointing to
the other channel's name. This means that if one channel
is hung up but the other moves on, it means that the
channel that moves on will have its application data
pointing at freed memory.

(issue ASTERISK-20335)
Reported by: aragon

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

main/features.c

index 03a4c74376893cb0f5f29802a920a79691cb0de8..7cb66bff7e995f91bd059ba16d80ae855fc775fa 100644 (file)
@@ -945,6 +945,33 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
        struct ast_channel *transferee, const char *type, format_t format, void *data,
        int timeout, int *outstate, const char *language);
 
+static const struct ast_datastore_info channel_app_data_datastore = {
+       .type = "Channel appdata datastore",
+       .destroy = ast_free_ptr,
+};
+
+static int set_chan_app_data(struct ast_channel *chan, const char *src_app_data)
+{
+       struct ast_datastore *datastore;
+       char *dst_app_data;
+
+       datastore = ast_datastore_alloc(&channel_app_data_datastore, NULL);
+       if (!datastore) {
+               return -1;
+       }
+
+       dst_app_data = ast_malloc(strlen(src_app_data) + 1);
+       if (!dst_app_data) {
+               ast_datastore_free(datastore);
+               return -1;
+       }
+
+       chan->data = strcpy(dst_app_data, src_app_data);
+       datastore->data = dst_app_data;
+       ast_channel_datastore_add(chan, datastore);
+       return 0;
+}
+
 /*!
  * \brief bridge the call 
  * \param data thread bridge.
@@ -958,9 +985,13 @@ static void *bridge_call_thread(void *data)
        struct ast_bridge_thread_obj *tobj = data;
 
        tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
-       tobj->chan->data = tobj->peer->name;
+       if (set_chan_app_data(tobj->chan, tobj->peer->name)) {
+               tobj->chan->data = "(Empty)";
+       }
        tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
-       tobj->peer->data = tobj->chan->name;
+       if (set_chan_app_data(tobj->peer, tobj->chan->name)) {
+               tobj->peer->data = "(Empty)";
+       }
 
        ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);