From b77e092994c1416a570dac1975f9a1282da2ee44 Mon Sep 17 00:00:00 2001 From: twilson Date: Fri, 10 Sep 2010 20:35:25 +0000 Subject: Merged revisions 286059 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r286059 | twilson | 2010-09-10 14:25:08 -0500 (Fri, 10 Sep 2010) | 16 lines 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.6.2@286115 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_local.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'channels') diff --git a/channels/chan_local.c b/channels/chan_local.c index 46451776f..3b843ce70 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -77,6 +77,7 @@ static int local_sendtext(struct ast_channel *ast, const char *text); static int local_devicestate(void *data); static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge); static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen); +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 = { .devicestate = local_devicestate, .bridged_channel = local_bridgedchannel, .queryoption = local_queryoption, + .setoption = local_setoption, }; struct local_pvt { @@ -126,6 +128,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) { -- cgit v1.2.3