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:
Mark Spencer
2005-03-04 06:47:24 +00:00
parent fba0b595ab
commit 18d9b26cf9
35 changed files with 1224 additions and 956 deletions

472
channel.c
View File

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