mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
Rework channel structure to eliminate "pvt" portion of channel (bug #3573)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5137 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
472
channel.c
472
channel.c
@@ -25,7 +25,6 @@
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/musiconhold.h>
|
||||
#include <asterisk/channel_pvt.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/file.h>
|
||||
@@ -67,11 +66,7 @@ unsigned long global_fin = 0, global_fout = 0;
|
||||
/* XXX Lock appropriately in more functions XXX */
|
||||
|
||||
struct chanlist {
|
||||
char type[80];
|
||||
char description[80];
|
||||
int capabilities;
|
||||
struct ast_channel * (*requester)(const char *type, int format, void *data, int *cause);
|
||||
int (*devicestate)(void *data);
|
||||
const struct ast_channel_tech *tech;
|
||||
struct chanlist *next;
|
||||
} *backends = NULL;
|
||||
struct ast_channel *channels = NULL;
|
||||
@@ -92,7 +87,7 @@ static int show_channeltypes(int fd, int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
while (cl) {
|
||||
ast_cli(fd, FORMAT, cl->type, cl->description);
|
||||
ast_cli(fd, FORMAT, cl->tech->type, cl->tech->description);
|
||||
cl = cl->next;
|
||||
}
|
||||
ast_mutex_unlock(&chlock);
|
||||
@@ -113,8 +108,8 @@ time_t myt;
|
||||
|
||||
/* if soft hangup flag, return true */
|
||||
if (chan->_softhangup) return 1;
|
||||
/* if no private structure, return true */
|
||||
if (!chan->pvt->pvt) return 1;
|
||||
/* if no technology private data, return true */
|
||||
if (!chan->tech_pvt) return 1;
|
||||
/* if no hangup scheduled, just return here */
|
||||
if (!chan->whentohangup) return 0;
|
||||
time(&myt); /* get current time */
|
||||
@@ -184,51 +179,39 @@ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
|
||||
return;
|
||||
}
|
||||
|
||||
int ast_channel_register(const char *type, const char *description, int capabilities,
|
||||
struct ast_channel *(*requester)(const char *type, int format, void *data, int *cause))
|
||||
int ast_channel_register(const struct ast_channel_tech *tech)
|
||||
{
|
||||
return ast_channel_register_ex(type, description, capabilities, requester, NULL);
|
||||
}
|
||||
struct chanlist *chan;
|
||||
|
||||
ast_mutex_lock(&chlock);
|
||||
|
||||
int ast_channel_register_ex(const char *type, const char *description, int capabilities,
|
||||
struct ast_channel *(*requester)(const char *type, int format, void *data, int *cause),
|
||||
int (*devicestate)(void *data))
|
||||
{
|
||||
struct chanlist *chan, *last=NULL;
|
||||
if (ast_mutex_lock(&chlock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock channel list\n");
|
||||
return -1;
|
||||
}
|
||||
chan = backends;
|
||||
while (chan) {
|
||||
if (!strcasecmp(type, chan->type)) {
|
||||
ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
|
||||
if (!strcasecmp(tech->type, chan->tech->type)) {
|
||||
ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", tech->type);
|
||||
ast_mutex_unlock(&chlock);
|
||||
return -1;
|
||||
}
|
||||
last = chan;
|
||||
chan = chan->next;
|
||||
}
|
||||
chan = malloc(sizeof(struct chanlist));
|
||||
|
||||
chan = malloc(sizeof(*chan));
|
||||
if (!chan) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
ast_mutex_unlock(&chlock);
|
||||
return -1;
|
||||
}
|
||||
strncpy(chan->type, type, sizeof(chan->type)-1);
|
||||
strncpy(chan->description, description, sizeof(chan->description)-1);
|
||||
chan->capabilities = capabilities;
|
||||
chan->requester = requester;
|
||||
chan->devicestate = devicestate;
|
||||
chan->next = NULL;
|
||||
if (last)
|
||||
last->next = chan;
|
||||
else
|
||||
backends = chan;
|
||||
chan->tech = tech;
|
||||
chan->next = backends;
|
||||
backends = chan;
|
||||
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
|
||||
else if (option_verbose > 1)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
|
||||
ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->tech->type, chan->tech->description);
|
||||
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->tech->type,
|
||||
chan->tech->description);
|
||||
|
||||
ast_mutex_unlock(&chlock);
|
||||
return 0;
|
||||
}
|
||||
@@ -302,95 +285,100 @@ int ast_best_codec(int fmts)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ast_channel_tech null_tech = {
|
||||
.type = "NULL",
|
||||
.description "Null channel (should not see this)",
|
||||
};
|
||||
|
||||
struct ast_channel *ast_channel_alloc(int needqueue)
|
||||
{
|
||||
struct ast_channel *tmp;
|
||||
struct ast_channel_pvt *pvt;
|
||||
int x;
|
||||
int flags;
|
||||
struct varshead *headp;
|
||||
|
||||
|
||||
|
||||
/* If shutting down, don't allocate any new channels */
|
||||
if (shutting_down)
|
||||
return NULL;
|
||||
|
||||
ast_mutex_lock(&chlock);
|
||||
tmp = malloc(sizeof(struct ast_channel));
|
||||
if (tmp) {
|
||||
memset(tmp, 0, sizeof(struct ast_channel));
|
||||
pvt = malloc(sizeof(struct ast_channel_pvt));
|
||||
if (pvt) {
|
||||
memset(pvt, 0, sizeof(struct ast_channel_pvt));
|
||||
tmp->sched = sched_context_create();
|
||||
if (tmp->sched) {
|
||||
for (x=0;x<AST_MAX_FDS - 1;x++)
|
||||
tmp->fds[x] = -1;
|
||||
if (!tmp) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
ast_mutex_unlock(&chlock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(tmp, 0, sizeof(struct ast_channel));
|
||||
tmp->sched = sched_context_create();
|
||||
if (!tmp->sched) {
|
||||
ast_log(LOG_WARNING, "Unable to create schedule context\n");
|
||||
free(tmp);
|
||||
ast_mutex_unlock(&chlock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (x=0;x<AST_MAX_FDS - 1;x++)
|
||||
tmp->fds[x] = -1;
|
||||
|
||||
#ifdef ZAPTEL_OPTIMIZATIONS
|
||||
tmp->timingfd = open("/dev/zap/timer", O_RDWR);
|
||||
if (tmp->timingfd > -1) {
|
||||
/* Check if timing interface supports new
|
||||
ping/pong scheme */
|
||||
flags = 1;
|
||||
if (!ioctl(tmp->timingfd, ZT_TIMERPONG, &flags))
|
||||
needqueue = 0;
|
||||
}
|
||||
tmp->timingfd = open("/dev/zap/timer", O_RDWR);
|
||||
if (tmp->timingfd > -1) {
|
||||
/* Check if timing interface supports new
|
||||
ping/pong scheme */
|
||||
flags = 1;
|
||||
if (!ioctl(tmp->timingfd, ZT_TIMERPONG, &flags))
|
||||
needqueue = 0;
|
||||
}
|
||||
#else
|
||||
tmp->timingfd = -1;
|
||||
tmp->timingfd = -1;
|
||||
#endif
|
||||
if (needqueue &&
|
||||
pipe(pvt->alertpipe)) {
|
||||
ast_log(LOG_WARNING, "Alert pipe creation failed!\n");
|
||||
free(pvt);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
pvt = NULL;
|
||||
} else {
|
||||
if (needqueue) {
|
||||
flags = fcntl(pvt->alertpipe[0], F_GETFL);
|
||||
fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK);
|
||||
flags = fcntl(pvt->alertpipe[1], F_GETFL);
|
||||
fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK);
|
||||
} else
|
||||
/* Make sure we've got it done right if they don't */
|
||||
pvt->alertpipe[0] = pvt->alertpipe[1] = -1;
|
||||
/* Always watch the alertpipe */
|
||||
tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0];
|
||||
/* And timing pipe */
|
||||
tmp->fds[AST_MAX_FDS-2] = tmp->timingfd;
|
||||
strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1);
|
||||
tmp->pvt = pvt;
|
||||
/* Initial state */
|
||||
tmp->_state = AST_STATE_DOWN;
|
||||
tmp->streamid = -1;
|
||||
tmp->appl = NULL;
|
||||
tmp->data = NULL;
|
||||
tmp->fin = global_fin;
|
||||
tmp->fout = global_fout;
|
||||
snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long)time(NULL), uniqueint++);
|
||||
headp=&tmp->varshead;
|
||||
ast_mutex_init(&tmp->lock);
|
||||
AST_LIST_HEAD_INIT(headp);
|
||||
strncpy(tmp->context, "default", sizeof(tmp->context)-1);
|
||||
strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1);
|
||||
strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
|
||||
tmp->priority=1;
|
||||
tmp->amaflags = ast_default_amaflags;
|
||||
strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1);
|
||||
tmp->next = channels;
|
||||
channels= tmp;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to create schedule context\n");
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
|
||||
if (needqueue) {
|
||||
if (pipe(tmp->alertpipe)) {
|
||||
ast_log(LOG_WARNING, "Alert pipe creation failed!\n");
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
ast_mutex_unlock(&chlock);
|
||||
return NULL;
|
||||
} else {
|
||||
flags = fcntl(tmp->alertpipe[0], F_GETFL);
|
||||
fcntl(tmp->alertpipe[0], F_SETFL, flags | O_NONBLOCK);
|
||||
flags = fcntl(tmp->alertpipe[1], F_GETFL);
|
||||
fcntl(tmp->alertpipe[1], F_SETFL, flags | O_NONBLOCK);
|
||||
}
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
/* Make sure we've got it done right if they don't */
|
||||
tmp->alertpipe[0] = tmp->alertpipe[1] = -1;
|
||||
|
||||
/* Always watch the alertpipe */
|
||||
tmp->fds[AST_MAX_FDS-1] = tmp->alertpipe[0];
|
||||
/* And timing pipe */
|
||||
tmp->fds[AST_MAX_FDS-2] = tmp->timingfd;
|
||||
strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1);
|
||||
/* Initial state */
|
||||
tmp->_state = AST_STATE_DOWN;
|
||||
tmp->streamid = -1;
|
||||
tmp->appl = NULL;
|
||||
tmp->data = NULL;
|
||||
tmp->fin = global_fin;
|
||||
tmp->fout = global_fout;
|
||||
snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long)time(NULL), uniqueint++);
|
||||
headp = &tmp->varshead;
|
||||
ast_mutex_init(&tmp->lock);
|
||||
AST_LIST_HEAD_INIT(headp);
|
||||
strncpy(tmp->context, "default", sizeof(tmp->context)-1);
|
||||
strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1);
|
||||
strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
|
||||
tmp->priority = 1;
|
||||
tmp->amaflags = ast_default_amaflags;
|
||||
strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1);
|
||||
|
||||
tmp->tech = &null_tech;
|
||||
|
||||
tmp->next = channels;
|
||||
channels = tmp;
|
||||
|
||||
ast_mutex_unlock(&chlock);
|
||||
return tmp;
|
||||
}
|
||||
@@ -409,7 +397,7 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin)
|
||||
}
|
||||
ast_mutex_lock(&chan->lock);
|
||||
prev = NULL;
|
||||
cur = chan->pvt->readq;
|
||||
cur = chan->readq;
|
||||
while(cur) {
|
||||
if ((cur->frametype == AST_FRAME_CONTROL) && (cur->subclass == AST_CONTROL_HANGUP)) {
|
||||
/* Don't bother actually queueing anything after a hangup */
|
||||
@@ -436,9 +424,9 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin)
|
||||
if (prev)
|
||||
prev->next = f;
|
||||
else
|
||||
chan->pvt->readq = f;
|
||||
if (chan->pvt->alertpipe[1] > -1) {
|
||||
if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah))
|
||||
chan->readq = f;
|
||||
if (chan->alertpipe[1] > -1) {
|
||||
if (write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah))
|
||||
ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
|
||||
chan->name, f->frametype, f->subclass, qlen, strerror(errno));
|
||||
#ifdef ZAPTEL_OPTIMIZATIONS
|
||||
@@ -632,8 +620,10 @@ void ast_channel_free(struct ast_channel *chan)
|
||||
ast_mutex_lock(&cur->lock);
|
||||
ast_mutex_unlock(&cur->lock);
|
||||
}
|
||||
if (chan->pvt->pvt)
|
||||
if (chan->tech_pvt) {
|
||||
ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
|
||||
free(chan->tech_pvt);
|
||||
}
|
||||
|
||||
strncpy(name, chan->name, sizeof(name)-1);
|
||||
|
||||
@@ -647,23 +637,23 @@ void ast_channel_free(struct ast_channel *chan)
|
||||
ast_moh_cleanup(chan);
|
||||
|
||||
/* Free translatosr */
|
||||
if (chan->pvt->readtrans)
|
||||
ast_translator_free_path(chan->pvt->readtrans);
|
||||
if (chan->pvt->writetrans)
|
||||
ast_translator_free_path(chan->pvt->writetrans);
|
||||
if (chan->readtrans)
|
||||
ast_translator_free_path(chan->readtrans);
|
||||
if (chan->writetrans)
|
||||
ast_translator_free_path(chan->writetrans);
|
||||
if (chan->pbx)
|
||||
ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
|
||||
free_cid(&chan->cid);
|
||||
ast_mutex_destroy(&chan->lock);
|
||||
/* Close pipes if appropriate */
|
||||
if ((fd = chan->pvt->alertpipe[0]) > -1)
|
||||
if ((fd = chan->alertpipe[0]) > -1)
|
||||
close(fd);
|
||||
if ((fd = chan->pvt->alertpipe[1]) > -1)
|
||||
if ((fd = chan->alertpipe[1]) > -1)
|
||||
close(fd);
|
||||
if ((fd = chan->timingfd) > -1)
|
||||
close(fd);
|
||||
f = chan->pvt->readq;
|
||||
chan->pvt->readq = NULL;
|
||||
f = chan->readq;
|
||||
chan->readq = NULL;
|
||||
while(f) {
|
||||
fp = f;
|
||||
f = f->next;
|
||||
@@ -678,10 +668,7 @@ void ast_channel_free(struct ast_channel *chan)
|
||||
/* printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata)); */
|
||||
ast_var_delete(vardata);
|
||||
}
|
||||
|
||||
|
||||
free(chan->pvt);
|
||||
chan->pvt = NULL;
|
||||
free(chan);
|
||||
ast_mutex_unlock(&chlock);
|
||||
|
||||
@@ -714,14 +701,14 @@ int ast_softhangup(struct ast_channel *chan, int cause)
|
||||
|
||||
static void free_translation(struct ast_channel *clone)
|
||||
{
|
||||
if (clone->pvt->writetrans)
|
||||
ast_translator_free_path(clone->pvt->writetrans);
|
||||
if (clone->pvt->readtrans)
|
||||
ast_translator_free_path(clone->pvt->readtrans);
|
||||
clone->pvt->writetrans = NULL;
|
||||
clone->pvt->readtrans = NULL;
|
||||
clone->pvt->rawwriteformat = clone->nativeformats;
|
||||
clone->pvt->rawreadformat = clone->nativeformats;
|
||||
if (clone->writetrans)
|
||||
ast_translator_free_path(clone->writetrans);
|
||||
if (clone->readtrans)
|
||||
ast_translator_free_path(clone->readtrans);
|
||||
clone->writetrans = NULL;
|
||||
clone->readtrans = NULL;
|
||||
clone->rawwriteformat = clone->nativeformats;
|
||||
clone->rawreadformat = clone->nativeformats;
|
||||
}
|
||||
|
||||
int ast_hangup(struct ast_channel *chan)
|
||||
@@ -775,8 +762,8 @@ int ast_hangup(struct ast_channel *chan)
|
||||
if (!ast_test_flag(chan, AST_FLAG_ZOMBIE)) {
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
|
||||
if (chan->pvt->hangup)
|
||||
res = chan->pvt->hangup(chan);
|
||||
if (chan->tech->hangup)
|
||||
res = chan->tech->hangup(chan);
|
||||
} else
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
|
||||
@@ -791,32 +778,34 @@ int ast_hangup(struct ast_channel *chan)
|
||||
return res;
|
||||
}
|
||||
|
||||
void ast_channel_unregister(const char *type)
|
||||
void ast_channel_unregister(const struct ast_channel_tech *tech)
|
||||
{
|
||||
struct chanlist *chan, *last=NULL;
|
||||
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type);
|
||||
if (ast_mutex_lock(&chlock)) {
|
||||
ast_log(LOG_WARNING, "Unable to lock channel list\n");
|
||||
return;
|
||||
}
|
||||
if (option_verbose > 1)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type);
|
||||
ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", tech->type);
|
||||
|
||||
ast_mutex_lock(&chlock);
|
||||
|
||||
chan = backends;
|
||||
while(chan) {
|
||||
if (!strcasecmp(chan->type, type)) {
|
||||
while (chan) {
|
||||
if (chan->tech == tech) {
|
||||
if (last)
|
||||
last->next = chan->next;
|
||||
else
|
||||
backends = backends->next;
|
||||
free(chan);
|
||||
ast_mutex_unlock(&chlock);
|
||||
|
||||
if (option_verbose > 1)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", tech->type);
|
||||
|
||||
return;
|
||||
}
|
||||
last = chan;
|
||||
chan = chan->next;
|
||||
}
|
||||
|
||||
ast_mutex_unlock(&chlock);
|
||||
}
|
||||
|
||||
@@ -832,8 +821,8 @@ int ast_answer(struct ast_channel *chan)
|
||||
switch(chan->_state) {
|
||||
case AST_STATE_RINGING:
|
||||
case AST_STATE_RING:
|
||||
if (chan->pvt->answer)
|
||||
res = chan->pvt->answer(chan);
|
||||
if (chan->tech->answer)
|
||||
res = chan->tech->answer(chan);
|
||||
ast_setstate(chan, AST_STATE_UP);
|
||||
if (chan->cdr)
|
||||
ast_cdr_answer(chan->cdr);
|
||||
@@ -1269,8 +1258,8 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
||||
|
||||
/* Read and ignore anything on the alertpipe, but read only
|
||||
one sizeof(blah) per frame that we send from it */
|
||||
if (chan->pvt->alertpipe[0] > -1) {
|
||||
read(chan->pvt->alertpipe[0], &blah, sizeof(blah));
|
||||
if (chan->alertpipe[0] > -1) {
|
||||
read(chan->alertpipe[0], &blah, sizeof(blah));
|
||||
}
|
||||
#ifdef ZAPTEL_OPTIMIZATIONS
|
||||
if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && ast_test_flag(chan, AST_FLAG_EXCEPTION)) {
|
||||
@@ -1285,7 +1274,7 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
||||
#if 0
|
||||
ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
|
||||
#endif
|
||||
if (!chan->pvt->readq || !chan->pvt->readq->next) {
|
||||
if (!chan->readq || !chan->readq->next) {
|
||||
/* Acknowledge PONG unless we need it again */
|
||||
#if 0
|
||||
ast_log(LOG_NOTICE, "Sending a PONG!\n");
|
||||
@@ -1318,9 +1307,9 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
||||
}
|
||||
#endif
|
||||
/* Check for pending read queue */
|
||||
if (chan->pvt->readq) {
|
||||
f = chan->pvt->readq;
|
||||
chan->pvt->readq = f->next;
|
||||
if (chan->readq) {
|
||||
f = chan->readq;
|
||||
chan->readq = f->next;
|
||||
/* Interpret hangup and return NULL */
|
||||
if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
|
||||
ast_frfree(f);
|
||||
@@ -1329,8 +1318,8 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
||||
} else {
|
||||
chan->blocker = pthread_self();
|
||||
if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) {
|
||||
if (chan->pvt->exception)
|
||||
f = chan->pvt->exception(chan);
|
||||
if (chan->tech->exception)
|
||||
f = chan->tech->exception(chan);
|
||||
else {
|
||||
ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
|
||||
f = &null_frame;
|
||||
@@ -1338,8 +1327,8 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
||||
/* Clear the exception flag */
|
||||
ast_clear_flag(chan, AST_FLAG_EXCEPTION);
|
||||
} else
|
||||
if (chan->pvt->read)
|
||||
f = chan->pvt->read(chan);
|
||||
if (chan->tech->read)
|
||||
f = chan->tech->read(chan);
|
||||
else
|
||||
ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
|
||||
}
|
||||
@@ -1374,8 +1363,8 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
||||
if (ast_writestream(chan->monitor->read_stream, f) < 0)
|
||||
ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
|
||||
}
|
||||
if (chan->pvt->readtrans) {
|
||||
f = ast_translate(chan->pvt->readtrans, f, 1);
|
||||
if (chan->readtrans) {
|
||||
f = ast_translate(chan->readtrans, f, 1);
|
||||
if (!f)
|
||||
f = &null_frame;
|
||||
}
|
||||
@@ -1449,10 +1438,10 @@ int ast_indicate(struct ast_channel *chan, int condition)
|
||||
if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))
|
||||
return -1;
|
||||
ast_mutex_lock(&chan->lock);
|
||||
if (chan->pvt->indicate)
|
||||
res = chan->pvt->indicate(chan, condition);
|
||||
if (chan->tech->indicate)
|
||||
res = chan->tech->indicate(chan, condition);
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
if (!chan->pvt->indicate || res) {
|
||||
if (!chan->tech->indicate || res) {
|
||||
/*
|
||||
* Device does not support (that) indication, lets fake
|
||||
* it by doing our own tone generation. (PM2002)
|
||||
@@ -1529,8 +1518,8 @@ int ast_sendtext(struct ast_channel *chan, char *text)
|
||||
if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan))
|
||||
return -1;
|
||||
CHECK_BLOCKING(chan);
|
||||
if (chan->pvt->send_text)
|
||||
res = chan->pvt->send_text(chan, text);
|
||||
if (chan->tech->send_text)
|
||||
res = chan->tech->send_text(chan, text);
|
||||
ast_clear_flag(chan, AST_FLAG_BLOCKING);
|
||||
return res;
|
||||
}
|
||||
@@ -1539,9 +1528,9 @@ static int do_senddigit(struct ast_channel *chan, char digit)
|
||||
{
|
||||
int res = -1;
|
||||
|
||||
if (chan->pvt->send_digit)
|
||||
res = chan->pvt->send_digit(chan, digit);
|
||||
if (!chan->pvt->send_digit || res) {
|
||||
if (chan->tech->send_digit)
|
||||
res = chan->tech->send_digit(chan, digit);
|
||||
if (!chan->tech->send_digit || res) {
|
||||
/*
|
||||
* Device does not support DTMF tones, lets fake
|
||||
* it by doing our own generation. (PM2002)
|
||||
@@ -1591,7 +1580,7 @@ int ast_prod(struct ast_channel *chan)
|
||||
/* Send an empty audio frame to get things moving */
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
|
||||
a.subclass = chan->pvt->rawwriteformat;
|
||||
a.subclass = chan->rawwriteformat;
|
||||
a.data = nothing + AST_FRIENDLY_OFFSET;
|
||||
a.src = "ast_prod";
|
||||
if (ast_write(chan, &a))
|
||||
@@ -1603,7 +1592,7 @@ int ast_prod(struct ast_channel *chan)
|
||||
int ast_write_video(struct ast_channel *chan, struct ast_frame *fr)
|
||||
{
|
||||
int res;
|
||||
if (!chan->pvt->write_video)
|
||||
if (!chan->tech->write_video)
|
||||
return 0;
|
||||
res = ast_write(chan, fr);
|
||||
if (!res)
|
||||
@@ -1657,32 +1646,32 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
||||
CHECK_BLOCKING(chan);
|
||||
break;
|
||||
case AST_FRAME_TEXT:
|
||||
if (chan->pvt->send_text)
|
||||
res = chan->pvt->send_text(chan, (char *) fr->data);
|
||||
if (chan->tech->send_text)
|
||||
res = chan->tech->send_text(chan, (char *) fr->data);
|
||||
else
|
||||
res = 0;
|
||||
break;
|
||||
case AST_FRAME_HTML:
|
||||
if (chan->pvt->send_html)
|
||||
res = chan->pvt->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen);
|
||||
if (chan->tech->send_html)
|
||||
res = chan->tech->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen);
|
||||
else
|
||||
res = 0;
|
||||
break;
|
||||
case AST_FRAME_VIDEO:
|
||||
/* XXX Handle translation of video codecs one day XXX */
|
||||
if (chan->pvt->write_video)
|
||||
res = chan->pvt->write_video(chan, fr);
|
||||
if (chan->tech->write_video)
|
||||
res = chan->tech->write_video(chan, fr);
|
||||
else
|
||||
res = 0;
|
||||
break;
|
||||
default:
|
||||
if (chan->pvt->write) {
|
||||
if (chan->pvt->writetrans) {
|
||||
f = ast_translate(chan->pvt->writetrans, fr, 0);
|
||||
if (chan->tech->write) {
|
||||
if (chan->writetrans) {
|
||||
f = ast_translate(chan->writetrans, fr, 0);
|
||||
} else
|
||||
f = fr;
|
||||
if (f) {
|
||||
res = chan->pvt->write(chan, f);
|
||||
res = chan->tech->write(chan, f);
|
||||
if( chan->monitor &&
|
||||
chan->monitor->write_stream &&
|
||||
f && ( f->frametype == AST_FRAME_VOICE ) ) {
|
||||
@@ -1746,14 +1735,14 @@ int ast_set_write_format(struct ast_channel *chan, int fmts)
|
||||
}
|
||||
|
||||
/* Now we have a good choice for both. We'll write using our native format. */
|
||||
chan->pvt->rawwriteformat = native;
|
||||
chan->rawwriteformat = native;
|
||||
/* User perspective is fmt */
|
||||
chan->writeformat = fmt;
|
||||
/* Free any write translation we have right now */
|
||||
if (chan->pvt->writetrans)
|
||||
ast_translator_free_path(chan->pvt->writetrans);
|
||||
if (chan->writetrans)
|
||||
ast_translator_free_path(chan->writetrans);
|
||||
/* Build a translation path from the user write format to the raw writing format */
|
||||
chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
|
||||
chan->writetrans = ast_translator_build_path(chan->rawwriteformat, chan->writeformat);
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat));
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
@@ -1779,14 +1768,14 @@ int ast_set_read_format(struct ast_channel *chan, int fmts)
|
||||
}
|
||||
|
||||
/* Now we have a good choice for both. We'll write using our native format. */
|
||||
chan->pvt->rawreadformat = native;
|
||||
chan->rawreadformat = native;
|
||||
/* User perspective is fmt */
|
||||
chan->readformat = fmt;
|
||||
/* Free any read translation we have right now */
|
||||
if (chan->pvt->readtrans)
|
||||
ast_translator_free_path(chan->pvt->readtrans);
|
||||
if (chan->readtrans)
|
||||
ast_translator_free_path(chan->readtrans);
|
||||
/* Build a translation path from the raw read format to the user reading format */
|
||||
chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
|
||||
chan->readtrans = ast_translator_build_path(chan->readformat, chan->rawreadformat);
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Set channel %s to read format %s\n",
|
||||
chan->name, ast_getformatname(chan->readformat));
|
||||
@@ -1934,18 +1923,18 @@ struct ast_channel *ast_request(const char *type, int format, void *data, int *c
|
||||
}
|
||||
chan = backends;
|
||||
while(chan) {
|
||||
if (!strcasecmp(type, chan->type)) {
|
||||
capabilities = chan->capabilities;
|
||||
if (!strcasecmp(type, chan->tech->type)) {
|
||||
capabilities = chan->tech->capabilities;
|
||||
fmt = format;
|
||||
res = ast_translator_best_choice(&fmt, &capabilities);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
|
||||
ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->tech->capabilities, format);
|
||||
ast_mutex_unlock(&chlock);
|
||||
return NULL;
|
||||
}
|
||||
ast_mutex_unlock(&chlock);
|
||||
if (chan->requester)
|
||||
c = chan->requester(type, capabilities, data, cause);
|
||||
if (chan->tech->requester)
|
||||
c = chan->tech->requester(type, capabilities, data, cause);
|
||||
if (c) {
|
||||
if (c->_state == AST_STATE_DOWN) {
|
||||
manager_event(EVENT_FLAG_CALL, "Newchannel",
|
||||
@@ -2010,12 +1999,12 @@ int ast_device_state(char *device)
|
||||
}
|
||||
chanls = backends;
|
||||
while(chanls) {
|
||||
if (!strcasecmp(tech, chanls->type)) {
|
||||
if (!strcasecmp(tech, chanls->tech->type)) {
|
||||
ast_mutex_unlock(&chlock);
|
||||
if (!chanls->devicestate)
|
||||
if (!chanls->tech->devicestate)
|
||||
return ast_parse_device_state(device);
|
||||
else {
|
||||
res = chanls->devicestate(number);
|
||||
res = chanls->tech->devicestate(number);
|
||||
if (res == AST_DEVICE_UNKNOWN)
|
||||
return ast_parse_device_state(device);
|
||||
else
|
||||
@@ -2037,8 +2026,8 @@ int ast_call(struct ast_channel *chan, char *addr, int timeout)
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
ast_mutex_lock(&chan->lock);
|
||||
if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan))
|
||||
if (chan->pvt->call)
|
||||
res = chan->pvt->call(chan, addr, timeout);
|
||||
if (chan->tech->call)
|
||||
res = chan->tech->call(chan, addr, timeout);
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
return res;
|
||||
}
|
||||
@@ -2052,8 +2041,8 @@ int ast_transfer(struct ast_channel *chan, char *dest)
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
ast_mutex_lock(&chan->lock);
|
||||
if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) {
|
||||
if (chan->pvt->transfer) {
|
||||
res = chan->pvt->transfer(chan, dest);
|
||||
if (chan->tech->transfer) {
|
||||
res = chan->tech->transfer(chan, dest);
|
||||
if (!res)
|
||||
res = 1;
|
||||
} else
|
||||
@@ -2146,22 +2135,22 @@ int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, in
|
||||
|
||||
int ast_channel_supports_html(struct ast_channel *chan)
|
||||
{
|
||||
if (chan->pvt->send_html)
|
||||
if (chan->tech->send_html)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_channel_sendhtml(struct ast_channel *chan, int subclass, char *data, int datalen)
|
||||
{
|
||||
if (chan->pvt->send_html)
|
||||
return chan->pvt->send_html(chan, subclass, data, datalen);
|
||||
if (chan->tech->send_html)
|
||||
return chan->tech->send_html(chan, subclass, data, datalen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ast_channel_sendurl(struct ast_channel *chan, char *url)
|
||||
{
|
||||
if (chan->pvt->send_html)
|
||||
return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
|
||||
if (chan->tech->send_html)
|
||||
return chan->tech->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2340,7 +2329,8 @@ int ast_do_masquerade(struct ast_channel *original)
|
||||
int res=0;
|
||||
int origstate;
|
||||
struct ast_frame *cur, *prev;
|
||||
struct ast_channel_pvt *p;
|
||||
const struct ast_channel_tech *t;
|
||||
void *t_pvt;
|
||||
struct ast_callerid tmpcid;
|
||||
struct ast_channel *clone = original->masq;
|
||||
int rformat = original->readformat;
|
||||
@@ -2391,15 +2381,39 @@ int ast_do_masquerade(struct ast_channel *original)
|
||||
manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
|
||||
manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
|
||||
|
||||
/* Swap the guts */
|
||||
p = original->pvt;
|
||||
original->pvt = clone->pvt;
|
||||
clone->pvt = p;
|
||||
/* Swap the technlogies */
|
||||
t = original->tech;
|
||||
original->tech = clone->tech;
|
||||
clone->tech = t;
|
||||
|
||||
t_pvt = original->tech_pvt;
|
||||
original->tech_pvt = clone->tech_pvt;
|
||||
clone->tech_pvt = t_pvt;
|
||||
|
||||
/* Swap the readq's */
|
||||
cur = original->readq;
|
||||
original->readq = clone->readq;
|
||||
clone->readq = cur;
|
||||
|
||||
/* Swap the alertpipes */
|
||||
for (i = 0; i < 2; i++) {
|
||||
x = original->alertpipe[i];
|
||||
original->alertpipe[i] = clone->alertpipe[i];
|
||||
clone->alertpipe[i] = x;
|
||||
}
|
||||
|
||||
/* Swap the raw formats */
|
||||
x = original->rawreadformat;
|
||||
original->rawreadformat = clone->rawreadformat;
|
||||
clone->rawreadformat = x;
|
||||
x = original->rawwriteformat;
|
||||
original->rawwriteformat = clone->rawwriteformat;
|
||||
clone->rawwriteformat = x;
|
||||
|
||||
/* Save any pending frames on both sides. Start by counting
|
||||
* how many we're going to need... */
|
||||
prev = NULL;
|
||||
cur = clone->pvt->readq;
|
||||
cur = clone->readq;
|
||||
x = 0;
|
||||
while(cur) {
|
||||
x++;
|
||||
@@ -2409,12 +2423,12 @@ int ast_do_masquerade(struct ast_channel *original)
|
||||
/* If we had any, prepend them to the ones already in the queue, and
|
||||
* load up the alertpipe */
|
||||
if (prev) {
|
||||
prev->next = original->pvt->readq;
|
||||
original->pvt->readq = clone->pvt->readq;
|
||||
clone->pvt->readq = NULL;
|
||||
if (original->pvt->alertpipe[1] > -1) {
|
||||
prev->next = original->readq;
|
||||
original->readq = clone->readq;
|
||||
clone->readq = NULL;
|
||||
if (original->alertpipe[1] > -1) {
|
||||
for (i=0;i<x;i++)
|
||||
write(original->pvt->alertpipe[1], &x, sizeof(x));
|
||||
write(original->alertpipe[1], &x, sizeof(x));
|
||||
}
|
||||
}
|
||||
clone->_softhangup = AST_SOFTHANGUP_DEV;
|
||||
@@ -2428,15 +2442,15 @@ int ast_do_masquerade(struct ast_channel *original)
|
||||
original->_state = clone->_state;
|
||||
clone->_state = origstate;
|
||||
|
||||
if (clone->pvt->fixup){
|
||||
res = clone->pvt->fixup(original, clone);
|
||||
if (clone->tech->fixup){
|
||||
res = clone->tech->fixup(original, clone);
|
||||
if (res)
|
||||
ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
|
||||
}
|
||||
|
||||
/* Start by disconnecting the original's physical side */
|
||||
if (clone->pvt->hangup)
|
||||
res = clone->pvt->hangup(clone);
|
||||
if (clone->tech->hangup)
|
||||
res = clone->tech->hangup(clone);
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n");
|
||||
ast_mutex_unlock(&clone->lock);
|
||||
@@ -2500,8 +2514,8 @@ int ast_do_masquerade(struct ast_channel *original)
|
||||
|
||||
/* Okay. Last thing is to let the channel driver know about all this mess, so he
|
||||
can fix up everything as best as possible */
|
||||
if (original->pvt->fixup) {
|
||||
res = original->pvt->fixup(clone, original);
|
||||
if (original->tech->fixup) {
|
||||
res = original->tech->fixup(clone, original);
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n",
|
||||
original->type, original->name);
|
||||
@@ -2622,8 +2636,8 @@ struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_channel *bridged;
|
||||
bridged = chan->_bridge;
|
||||
if (bridged && bridged->pvt->bridged_channel)
|
||||
bridged = bridged->pvt->bridged_channel(chan, bridged);
|
||||
if (bridged && bridged->tech->bridged_channel)
|
||||
bridged = bridged->tech->bridged_channel(chan, bridged);
|
||||
return bridged;
|
||||
}
|
||||
|
||||
@@ -2772,12 +2786,12 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct as
|
||||
ast_log(LOG_DEBUG, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",c0->name,c1->name,ast_test_flag(c0, AST_FLAG_ZOMBIE)?"Yes":"No",ast_check_hangup(c0)?"Yes":"No",ast_test_flag(c1, AST_FLAG_ZOMBIE)?"Yes":"No",ast_check_hangup(c1)?"Yes":"No");
|
||||
break;
|
||||
}
|
||||
if (c0->pvt->bridge && config->timelimit==0 &&
|
||||
(c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
|
||||
if (c0->tech->bridge && config->timelimit==0 &&
|
||||
(c0->tech->bridge == c1->tech->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
|
||||
/* Looks like they share a bridge code */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
|
||||
if (!(res = c0->pvt->bridge(c0, c1, config->flags, fo, rc))) {
|
||||
if (!(res = c0->tech->bridge(c0, c1, config->flags, fo, rc))) {
|
||||
c0->_bridge = NULL;
|
||||
c1->_bridge = NULL;
|
||||
manager_event(EVENT_FLAG_CALL, "Unlink",
|
||||
@@ -2903,8 +2917,8 @@ tackygoto:
|
||||
int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int datalen, int block)
|
||||
{
|
||||
int res;
|
||||
if (chan->pvt->setoption) {
|
||||
res = chan->pvt->setoption(chan, option, data, datalen);
|
||||
if (chan->tech->setoption) {
|
||||
res = chan->tech->setoption(chan, option, data, datalen);
|
||||
if (res < 0)
|
||||
return res;
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user