aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authortwilson <twilson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-10 19:25:08 +0000
committertwilson <twilson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-09-10 19:25:08 +0000
commit2d7639134c53e53ef345904913933b3eead99694 (patch)
tree26999f806d1bba5e9f5df58d7485d0ba25e77974 /channels
parent6368131c6cbe811d9348bf387b9f62ae40b9fb37 (diff)
Inherit CHANNEL() writes to both sides of a Local channel
Having Local (/n) channels as queue members and setting the language in the extension with Set(CHANNEL(language)=fr) sets the language on the Local/...,2 channel. Hold time report playbacks happen on the Local/...,1 channel and therefor do not play in the specified language. This patch modifies func_channel_write to call the setoption callback and pass the CHANNEL() write info to the callback. chan_local uses this information to look up the other side of the channel and apply the same changes to it. (closes issue #17673) Reported by: Guggemand Review: https://reviewboard.asterisk.org/r/903/ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@286059 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_local.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/channels/chan_local.c b/channels/chan_local.c
index 7fa6968cc..f49eb0b2f 100644
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -79,6 +79,7 @@ static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
static int local_sendtext(struct ast_channel *ast, const char *text);
static int local_devicestate(void *data);
+static int local_setoption(struct ast_channel *chan, int option, void *data, int datalen);
/* PBX interface structure for channel registration */
static const struct ast_channel_tech local_tech = {
@@ -100,6 +101,7 @@ static const struct ast_channel_tech local_tech = {
.send_html = local_sendhtml,
.send_text = local_sendtext,
.devicestate = local_devicestate,
+ .setoption = local_setoption,
};
struct local_pvt {
@@ -124,6 +126,71 @@ struct local_pvt {
static AST_LIST_HEAD_STATIC(locals, local_pvt);
+static int local_setoption(struct ast_channel *chan, int option, void * data, int datalen)
+{
+ int res;
+ struct local_pvt *p;
+ struct ast_channel *otherchan;
+ ast_chan_write_info_t *write_info;
+
+ if (option != AST_OPTION_CHANNEL_WRITE) {
+ return 0;
+ }
+
+ write_info = data;
+
+ if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) {
+ ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n");
+ return -1;
+ }
+
+
+startover:
+ ast_channel_lock(chan);
+
+ p = chan->tech_pvt;
+ if (!p) {
+ ast_channel_unlock(chan);
+ ast_log(LOG_WARNING, "Could not update other side of %s, local_pvt went away.\n", chan->name);
+ return -1;
+ }
+
+ while (ast_mutex_trylock(&p->lock)) {
+ ast_channel_unlock(chan);
+ sched_yield();
+ ast_channel_lock(chan);
+ p = chan->tech_pvt;
+ if (!p) {
+ ast_channel_unlock(chan);
+ ast_log(LOG_WARNING, "Could not update other side of %s, local_pvt went away.\n", chan->name);
+ return -1;
+ }
+ }
+
+ otherchan = (write_info->chan == p->owner) ? p->chan : p->owner;
+
+ if (!otherchan || otherchan == write_info->chan) {
+ ast_mutex_unlock(&p->lock);
+ ast_channel_unlock(chan);
+ ast_log(LOG_WARNING, "Could not update other side of %s, other side went away.\n", chan->name);
+ return 0;
+ }
+
+ if (ast_channel_trylock(otherchan)) {
+ ast_mutex_unlock(&p->lock);
+ ast_channel_unlock(chan);
+ goto startover;
+ }
+
+ res = write_info->write_fn(otherchan, write_info->function, write_info->data, write_info->value);
+
+ ast_channel_unlock(otherchan);
+ ast_mutex_unlock(&p->lock);
+ ast_channel_unlock(chan);
+
+ return res;
+}
+
/*! \brief Adds devicestate to local channels */
static int local_devicestate(void *data)
{