mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-19 19:52:48 +00:00
Merged revisions 286115 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.6.2 ................ r286115 | twilson | 2010-09-10 15:35:25 -0500 (Fri, 10 Sep 2010) | 23 lines 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.8@286189 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -95,6 +95,7 @@ static int local_sendtext(struct ast_channel *ast, const char *text);
|
|||||||
static int local_devicestate(void *data);
|
static int local_devicestate(void *data);
|
||||||
static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
|
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_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 */
|
/* PBX interface structure for channel registration */
|
||||||
static const struct ast_channel_tech local_tech = {
|
static const struct ast_channel_tech local_tech = {
|
||||||
@@ -118,6 +119,7 @@ static const struct ast_channel_tech local_tech = {
|
|||||||
.devicestate = local_devicestate,
|
.devicestate = local_devicestate,
|
||||||
.bridged_channel = local_bridgedchannel,
|
.bridged_channel = local_bridgedchannel,
|
||||||
.queryoption = local_queryoption,
|
.queryoption = local_queryoption,
|
||||||
|
.setoption = local_setoption,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief the local pvt structure for all channels
|
/*! \brief the local pvt structure for all channels
|
||||||
@@ -151,6 +153,71 @@ struct local_pvt {
|
|||||||
|
|
||||||
static AST_LIST_HEAD_STATIC(locals, 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 -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 */
|
/*! \brief Adds devicestate to local channels */
|
||||||
static int local_devicestate(void *data)
|
static int local_devicestate(void *data)
|
||||||
{
|
{
|
||||||
|
@@ -378,7 +378,7 @@ static int func_channel_read(struct ast_channel *chan, const char *function,
|
|||||||
return ret;
|
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)
|
char *data, const char *value)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -496,6 +496,24 @@ static int func_channel_write(struct ast_channel *chan, const char *function,
|
|||||||
return ret;
|
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 = {
|
static struct ast_custom_function channel_function = {
|
||||||
.name = "CHANNEL",
|
.name = "CHANNEL",
|
||||||
.read = func_channel_read,
|
.read = func_channel_read,
|
||||||
|
@@ -468,6 +468,27 @@ struct ast_set_party_redirecting {
|
|||||||
struct ast_set_party_id to;
|
struct ast_set_party_id to;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! \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 read2 function */
|
||||||
|
typedef int (*ast_acf_read2_fn_t)(struct ast_channel *, const char *, char *, struct ast_str **, ssize_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
|
* \brief
|
||||||
* Structure to describe a channel "technology", ie a channel driver
|
* Structure to describe a channel "technology", ie a channel driver
|
||||||
|
@@ -436,6 +436,13 @@ enum ast_control_transfer {
|
|||||||
/*! Explicitly enable or disable echo cancelation for the given channel */
|
/*! Explicitly enable or disable echo cancelation for the given channel */
|
||||||
#define AST_OPTION_ECHOCAN 8
|
#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.
|
* Read-only. Allows query current status of T38 on the channel.
|
||||||
* data: ast_t38state
|
* data: ast_t38state
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#ifndef _ASTERISK_PBX_H
|
#ifndef _ASTERISK_PBX_H
|
||||||
#define _ASTERISK_PBX_H
|
#define _ASTERISK_PBX_H
|
||||||
|
|
||||||
|
#include "asterisk/channel.h"
|
||||||
#include "asterisk/sched.h"
|
#include "asterisk/sched.h"
|
||||||
#include "asterisk/devicestate.h"
|
#include "asterisk/devicestate.h"
|
||||||
#include "asterisk/chanvars.h"
|
#include "asterisk/chanvars.h"
|
||||||
@@ -89,7 +90,7 @@ struct ast_custom_function {
|
|||||||
);
|
);
|
||||||
enum ast_doc_src docsrc; /*!< Where the documentation come from */
|
enum ast_doc_src docsrc; /*!< Where the documentation come from */
|
||||||
/*! Read function, if read is supported */
|
/*! Read function, if read is supported */
|
||||||
int (*read)(struct ast_channel *, const char *, char *, char *, size_t);
|
ast_acf_read_fn_t read; /*!< Read function, if read is supported */
|
||||||
/*! Read function, if read is supported. Note: only one of read or read2
|
/*! Read function, if read is supported. Note: only one of read or read2
|
||||||
* needs to be implemented. In new code, read2 should be implemented as
|
* needs to be implemented. In new code, read2 should be implemented as
|
||||||
* the way forward, but they should return identical results, within the
|
* the way forward, but they should return identical results, within the
|
||||||
@@ -97,11 +98,11 @@ struct ast_custom_function {
|
|||||||
* read function is handed a 16-byte buffer, and the result is 17 bytes
|
* read function is handed a 16-byte buffer, and the result is 17 bytes
|
||||||
* long, then the first 15 bytes (remember NULL terminator) should be
|
* long, then the first 15 bytes (remember NULL terminator) should be
|
||||||
* the same for both the read and the read2 methods. */
|
* the same for both the read and the read2 methods. */
|
||||||
int (*read2)(struct ast_channel *, const char *, char *, struct ast_str **, ssize_t);
|
ast_acf_read2_fn_t read2;
|
||||||
/*! If no read2 function is provided, what maximum size? */
|
/*! If no read2 function is provided, what maximum size? */
|
||||||
size_t read_max;
|
size_t read_max;
|
||||||
/*! Write function, if write is supported */
|
/*! Write function, if write is supported */
|
||||||
int (*write)(struct ast_channel *, const char *, char *, const char *);
|
ast_acf_write_fn_t write; /*!< Write function, if write is supported */
|
||||||
struct ast_module *mod; /*!< Module this custom function belongs to */
|
struct ast_module *mod; /*!< Module this custom function belongs to */
|
||||||
AST_RWLIST_ENTRY(ast_custom_function) acflist;
|
AST_RWLIST_ENTRY(ast_custom_function) acflist;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user