summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2012-09-11 21:13:26 +0000
committerMark Michelson <mmichelson@digium.com>2012-09-11 21:13:26 +0000
commitae5aaefd88224c20d246087b3e4277b6c97545cb (patch)
treeccc3d498b445a2afe5c7ba08020e33d26f706951
parent3e17426e89c62486d03a3fbd8ae654faf479e941 (diff)
Fix bad channel application data reference.
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 ........ Merged revisions 372840 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 372841 from http://svn.asterisk.org/svn/asterisk/branches/10 ........ Merged revisions 372886 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@372887 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--main/features.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/main/features.c b/main/features.c
index 4cfbcfb68..0650129c0 100644
--- a/main/features.c
+++ b/main/features.c
@@ -1087,6 +1087,33 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, const char *addr,
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;
+ }
+
+ ast_channel_data_set(chan, 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.
@@ -1106,9 +1133,13 @@ static void *bridge_call_thread(void *data)
}
ast_channel_appl_set(tobj->chan, !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge");
- ast_channel_data_set(tobj->chan, ast_channel_name(tobj->peer));
+ if (set_chan_app_data(tobj->chan, ast_channel_name(tobj->peer))) {
+ ast_channel_data_set(tobj->chan, "(Empty)");
+ }
ast_channel_appl_set(tobj->peer, !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge");
- ast_channel_data_set(tobj->peer, ast_channel_name(tobj->chan));
+ if (set_chan_app_data(tobj->peer, ast_channel_name(tobj->chan))) {
+ ast_channel_data_set(tobj->peer, "(Empty)");
+ }
ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);