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: https://origsvn.digium.com/svn/asterisk/branches/1.6.2@286115 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.2
Terry Wilson 15 years ago
parent a08ad772b9
commit a6ecd54058

@ -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)
{

@ -278,7 +278,7 @@ static int func_channel_read(struct ast_channel *chan, const char *function,
return ret;
}
static int func_channel_write(struct ast_channel *chan, const char *function,
static int func_channel_write_real(struct ast_channel *chan, const char *function,
char *data, const char *value)
{
int ret = 0;
@ -344,6 +344,24 @@ static int func_channel_write(struct ast_channel *chan, const char *function,
return ret;
}
static int func_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value)
{
int res;
ast_chan_write_info_t write_info = {
.version = AST_CHAN_WRITE_INFO_T_VERSION,
.write_fn = func_channel_write_real,
.chan = chan,
.function = function,
.data = data,
.value = value,
};
res = func_channel_write_real(chan, function, data, value);
ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0);
return res;
}
static struct ast_custom_function channel_function = {
.name = "CHANNEL",
.read = func_channel_read,

@ -210,6 +210,24 @@ struct ast_callerid {
int cid_tns; /*!< Callerid Transit Network Select */
};
/*! \brief Typedef for a custom read function */
typedef int (*ast_acf_read_fn_t)(struct ast_channel *, const char *, char *, char *, size_t);
/*! \brief Typedef for a custom write function */
typedef int (*ast_acf_write_fn_t)(struct ast_channel *, const char *, char *, const char *);
/*! \brief Structure to handle passing func_channel_write info to channels via setoption */
typedef struct {
/*! \brief ast_chan_write_info_t version. Must be incremented if structure is changed */
#define AST_CHAN_WRITE_INFO_T_VERSION 1
uint32_t version;
ast_acf_write_fn_t write_fn;
struct ast_channel *chan;
const char *function;
char *data;
const char *value;
} ast_chan_write_info_t;
/*! \brief
Structure to describe a channel "technology", ie a channel driver
See for examples:

@ -400,6 +400,13 @@ struct ast_control_t38_parameters {
/*! Explicitly enable or disable echo cancelation for the given channel */
#define AST_OPTION_ECHOCAN 8
/*! \brief Handle channel write data
* If a channel needs to process the data from a func_channel write operation
* after func_channel_write executes, it can define the setoption callback
* and process this option. A pointer to an ast_chan_write_info_t will be passed.
* */
#define AST_OPTION_CHANNEL_WRITE 9
/* !
* Read-only. Allows query current status of T38 on the channel.
* data: ast_t38state

@ -90,8 +90,8 @@ struct ast_custom_function {
AST_STRING_FIELD(seealso); /*!< See also */
);
enum ast_doc_src docsrc; /*!< Where the documentation come from */
int (*read)(struct ast_channel *, const char *, char *, char *, size_t); /*!< Read function, if read is supported */
int (*write)(struct ast_channel *, const char *, char *, const char *); /*!< Write function, if write is supported */
ast_acf_read_fn_t read; /*!< Read function, if read is supported */
ast_acf_write_fn_t write; /*!< Write function, if write is supported */
struct ast_module *mod; /*!< Module this custom function belongs to */
AST_RWLIST_ENTRY(ast_custom_function) acflist;
};

Loading…
Cancel
Save