mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-08 14:17:02 +00:00
Version 0.1.9 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
221
channel.c
221
channel.c
@@ -128,6 +128,42 @@ char *ast_state2str(int state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ast_best_codec(int fmts)
|
||||||
|
{
|
||||||
|
/* This just our opinion, expressed in code. We are asked to choose
|
||||||
|
the best codec to use, given no information */
|
||||||
|
int x;
|
||||||
|
static int prefs[] =
|
||||||
|
{
|
||||||
|
/* Okay, ulaw is used by all telephony equipment, so start with it */
|
||||||
|
AST_FORMAT_ULAW,
|
||||||
|
/* Unless of course, you're a silly European, so then prefer ALAW */
|
||||||
|
AST_FORMAT_ALAW,
|
||||||
|
/* Okay, well, signed linear is easy to translate into other stuff */
|
||||||
|
AST_FORMAT_SLINEAR,
|
||||||
|
/* ADPCM has great sound quality and is still pretty easy to translate */
|
||||||
|
AST_FORMAT_ADPCM,
|
||||||
|
/* Okay, we're down to vocoders now, so pick GSM because it's small and easier to
|
||||||
|
translate and sounds pretty good */
|
||||||
|
AST_FORMAT_GSM,
|
||||||
|
/* Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough
|
||||||
|
to use it */
|
||||||
|
AST_FORMAT_LPC10,
|
||||||
|
/* Down to G.723.1 which is proprietary but at least designed for voice */
|
||||||
|
AST_FORMAT_G723_1,
|
||||||
|
/* Last and least, MP3 which was of course never designed for real-time voice */
|
||||||
|
AST_FORMAT_MP3,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
for (x=0;x<sizeof(prefs) / sizeof(prefs[0]); x++)
|
||||||
|
if (fmts & prefs[x])
|
||||||
|
return prefs[x];
|
||||||
|
ast_log(LOG_WARNING, "Don't know any of 0x%x formats\n", fmts);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct ast_channel *ast_channel_alloc(void)
|
struct ast_channel *ast_channel_alloc(void)
|
||||||
{
|
{
|
||||||
struct ast_channel *tmp;
|
struct ast_channel *tmp;
|
||||||
@@ -174,6 +210,22 @@ struct ast_channel *ast_channel_alloc(void)
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ast_channel_defer_dtmf(struct ast_channel *chan)
|
||||||
|
{
|
||||||
|
int pre = 0;
|
||||||
|
if (chan) {
|
||||||
|
pre = chan->deferdtmf;
|
||||||
|
chan->deferdtmf = 1;
|
||||||
|
}
|
||||||
|
return pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_channel_undefer_dtmf(struct ast_channel *chan)
|
||||||
|
{
|
||||||
|
if (chan)
|
||||||
|
chan->deferdtmf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct ast_channel *ast_channel_walk(struct ast_channel *prev)
|
struct ast_channel *ast_channel_walk(struct ast_channel *prev)
|
||||||
{
|
{
|
||||||
struct ast_channel *l, *ret=NULL;
|
struct ast_channel *l, *ret=NULL;
|
||||||
@@ -243,19 +295,37 @@ int ast_softhangup(struct ast_channel *chan)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
int ast_hangup(struct ast_channel *chan)
|
int ast_hangup(struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
/* Don't actually hang up a channel that will masquerade as someone else, or
|
/* Don't actually hang up a channel that will masquerade as someone else, or
|
||||||
if someone is going to masquerade as us */
|
if someone is going to masquerade as us */
|
||||||
if (chan->masq)
|
ast_pthread_mutex_lock(&chan->lock);
|
||||||
|
if (chan->masq) {
|
||||||
|
ast_log(LOG_WARNING, "We're getting hung up, but someone is trying to masq into us?!?\n");
|
||||||
|
ast_pthread_mutex_unlock(&chan->lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
/* If this channel is one which will be masqueraded into something,
|
/* If this channel is one which will be masqueraded into something,
|
||||||
mark it as a zombie already, so we know to free it later */
|
mark it as a zombie already, so we know to free it later */
|
||||||
if (chan->masqr) {
|
if (chan->masqr) {
|
||||||
|
ast_pthread_mutex_unlock(&chan->lock);
|
||||||
chan->zombie=1;
|
chan->zombie=1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
free_translation(chan);
|
||||||
if (chan->stream)
|
if (chan->stream)
|
||||||
ast_stopstream(chan);
|
ast_stopstream(chan);
|
||||||
if (chan->sched)
|
if (chan->sched)
|
||||||
@@ -275,6 +345,7 @@ int ast_hangup(struct ast_channel *chan)
|
|||||||
if (option_debug)
|
if (option_debug)
|
||||||
ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
|
ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
|
||||||
|
|
||||||
|
ast_pthread_mutex_unlock(&chan->lock);
|
||||||
ast_channel_free(chan);
|
ast_channel_free(chan);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -307,15 +378,17 @@ void ast_channel_unregister(char *type)
|
|||||||
|
|
||||||
int ast_answer(struct ast_channel *chan)
|
int ast_answer(struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
|
int res = 0;
|
||||||
/* Stop if we're a zombie or need a soft hangup */
|
/* Stop if we're a zombie or need a soft hangup */
|
||||||
if (chan->zombie || chan->softhangup)
|
if (chan->zombie || chan->softhangup)
|
||||||
return -1;
|
return -1;
|
||||||
switch(chan->state) {
|
switch(chan->state) {
|
||||||
case AST_STATE_RING:
|
|
||||||
case AST_STATE_RINGING:
|
case AST_STATE_RINGING:
|
||||||
|
case AST_STATE_RING:
|
||||||
if (chan->pvt->answer)
|
if (chan->pvt->answer)
|
||||||
return chan->pvt->answer(chan);
|
res = chan->pvt->answer(chan);
|
||||||
chan->state = AST_STATE_UP;
|
chan->state = AST_STATE_UP;
|
||||||
|
return res;
|
||||||
break;
|
break;
|
||||||
case AST_STATE_UP:
|
case AST_STATE_UP:
|
||||||
break;
|
break;
|
||||||
@@ -371,7 +444,8 @@ int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
|
|||||||
|
|
||||||
static int ast_do_masquerade(struct ast_channel *original);
|
static int ast_do_masquerade(struct ast_channel *original);
|
||||||
|
|
||||||
struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
|
struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds,
|
||||||
|
int *exception, int *outfd, int *ms)
|
||||||
{
|
{
|
||||||
/* Wait for x amount of time on a file descriptor to have input. */
|
/* Wait for x amount of time on a file descriptor to have input. */
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@@ -379,6 +453,10 @@ struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
|
|||||||
int res;
|
int res;
|
||||||
int x, y, max=-1;
|
int x, y, max=-1;
|
||||||
struct ast_channel *winner = NULL;
|
struct ast_channel *winner = NULL;
|
||||||
|
if (outfd)
|
||||||
|
*outfd = -1;
|
||||||
|
if (exception)
|
||||||
|
*exception = 0;
|
||||||
|
|
||||||
/* Perform any pending masquerades */
|
/* Perform any pending masquerades */
|
||||||
for (x=0;x<n;x++) {
|
for (x=0;x<n;x++) {
|
||||||
@@ -406,6 +484,12 @@ struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
|
|||||||
}
|
}
|
||||||
CHECK_BLOCKING(c[x]);
|
CHECK_BLOCKING(c[x]);
|
||||||
}
|
}
|
||||||
|
for (x=0;x<nfds; x++) {
|
||||||
|
FD_SET(fds[x], &rfds);
|
||||||
|
FD_SET(fds[x], &efds);
|
||||||
|
if (fds[x] > max)
|
||||||
|
max = fds[x];
|
||||||
|
}
|
||||||
if (*ms >= 0)
|
if (*ms >= 0)
|
||||||
res = select(max + 1, &rfds, NULL, &efds, &tv);
|
res = select(max + 1, &rfds, NULL, &efds, &tv);
|
||||||
else
|
else
|
||||||
@@ -436,16 +520,35 @@ struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (x=0;x<nfds;x++) {
|
||||||
|
if ((FD_ISSET(fds[x], &rfds) || FD_ISSET(fds[x], &efds)) && !winner) {
|
||||||
|
if (outfd)
|
||||||
|
*outfd = fds[x];
|
||||||
|
if (FD_ISSET(fds[x], &efds) && exception)
|
||||||
|
*exception = 1;
|
||||||
|
winner = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
*ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
*ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
return winner;
|
return winner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
|
||||||
|
{
|
||||||
|
return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
|
||||||
|
}
|
||||||
|
|
||||||
int ast_waitfor(struct ast_channel *c, int ms)
|
int ast_waitfor(struct ast_channel *c, int ms)
|
||||||
{
|
{
|
||||||
struct ast_channel *chan;
|
struct ast_channel *chan;
|
||||||
|
int oldms = ms;
|
||||||
chan = ast_waitfor_n(&c, 1, &ms);
|
chan = ast_waitfor_n(&c, 1, &ms);
|
||||||
if (ms < 0)
|
if (ms < 0) {
|
||||||
|
if (oldms < 0)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
return ms;
|
return ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,6 +603,16 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!chan->deferdtmf && strlen(chan->dtmfq)) {
|
||||||
|
/* We have DTMF that has been deferred. Return it now */
|
||||||
|
chan->dtmff.frametype = AST_FRAME_DTMF;
|
||||||
|
chan->dtmff.subclass = chan->dtmfq[0];
|
||||||
|
/* Drop first digit */
|
||||||
|
memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
|
||||||
|
pthread_mutex_unlock(&chan->lock);
|
||||||
|
return &chan->dtmff;
|
||||||
|
}
|
||||||
|
|
||||||
chan->blocker = pthread_self();
|
chan->blocker = pthread_self();
|
||||||
if (chan->exception) {
|
if (chan->exception) {
|
||||||
if (chan->pvt->exception)
|
if (chan->pvt->exception)
|
||||||
@@ -523,6 +636,13 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
|||||||
/* Make sure we always return NULL in the future */
|
/* Make sure we always return NULL in the future */
|
||||||
if (!f)
|
if (!f)
|
||||||
chan->softhangup = 1;
|
chan->softhangup = 1;
|
||||||
|
else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
|
||||||
|
if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
|
||||||
|
chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
|
||||||
|
else
|
||||||
|
ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
|
||||||
|
f = &null_frame;
|
||||||
|
}
|
||||||
pthread_mutex_unlock(&chan->lock);
|
pthread_mutex_unlock(&chan->lock);
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
@@ -727,9 +847,13 @@ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int fti
|
|||||||
}
|
}
|
||||||
if (d < 0)
|
if (d < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (d == 0) {
|
||||||
|
s[pos]='\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (!strchr(enders, d))
|
if (!strchr(enders, d))
|
||||||
s[pos++] = d;
|
s[pos++] = d;
|
||||||
if ((d == 0) || strchr(enders, d) || (pos >= len - 1)) {
|
if (strchr(enders, d) || (pos >= len - 1)) {
|
||||||
s[pos]='\0';
|
s[pos]='\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -739,6 +863,27 @@ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int fti
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ast_channel_supports_html(struct ast_channel *chan)
|
||||||
|
{
|
||||||
|
if (chan->pvt->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);
|
||||||
|
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);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
|
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
|
||||||
{
|
{
|
||||||
int peerf;
|
int peerf;
|
||||||
@@ -812,13 +957,23 @@ static int ast_do_masquerade(struct ast_channel *original)
|
|||||||
char *tmp;
|
char *tmp;
|
||||||
struct ast_channel_pvt *p;
|
struct ast_channel_pvt *p;
|
||||||
struct ast_channel *clone = original->masq;
|
struct ast_channel *clone = original->masq;
|
||||||
|
int rformat = original->readformat;
|
||||||
|
int wformat = original->writeformat;
|
||||||
|
|
||||||
|
#if 0
|
||||||
ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
|
ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
|
||||||
clone->name, clone->state, original->name, original->state);
|
clone->name, clone->state, original->name, original->state);
|
||||||
|
#endif
|
||||||
/* XXX This is a seriously wacked out operation. We're essentially putting the guts of
|
/* XXX This is a seriously wacked out operation. We're essentially putting the guts of
|
||||||
the clone channel into the original channel. Start by killing off the original
|
the clone channel into the original channel. Start by killing off the original
|
||||||
channel's backend. I'm not sure we're going to keep this function, because
|
channel's backend. I'm not sure we're going to keep this function, because
|
||||||
while the features are nice, the cost is very high in terms of pure nastiness. XXX */
|
while the features are nice, the cost is very high in terms of pure nastiness. XXX */
|
||||||
|
|
||||||
|
/* Having remembered the original read/write formats, we turn off any translation on either
|
||||||
|
one */
|
||||||
|
free_translation(clone);
|
||||||
|
free_translation(original);
|
||||||
|
|
||||||
/* We need the clone's lock, too */
|
/* We need the clone's lock, too */
|
||||||
pthread_mutex_lock(&clone->lock);
|
pthread_mutex_lock(&clone->lock);
|
||||||
|
|
||||||
@@ -837,6 +992,15 @@ static int ast_do_masquerade(struct ast_channel *original)
|
|||||||
original->pvt = clone->pvt;
|
original->pvt = clone->pvt;
|
||||||
clone->pvt = p;
|
clone->pvt = p;
|
||||||
|
|
||||||
|
clone->softhangup = 1;
|
||||||
|
|
||||||
|
|
||||||
|
if (clone->pvt->fixup){
|
||||||
|
res = clone->pvt->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 */
|
/* Start by disconnecting the original's physical side */
|
||||||
if (clone->pvt->hangup)
|
if (clone->pvt->hangup)
|
||||||
res = clone->pvt->hangup(clone);
|
res = clone->pvt->hangup(clone);
|
||||||
@@ -877,6 +1041,9 @@ static int ast_do_masquerade(struct ast_channel *original)
|
|||||||
original->callerid = clone->callerid;
|
original->callerid = clone->callerid;
|
||||||
clone->callerid = tmp;
|
clone->callerid = tmp;
|
||||||
|
|
||||||
|
/* Our native formats are different now */
|
||||||
|
original->nativeformats = clone->nativeformats;
|
||||||
|
|
||||||
/* Context, extension, priority, app data, jump table, remain the same */
|
/* Context, extension, priority, app data, jump table, remain the same */
|
||||||
/* pvt switches. pbx stays the same, as does next */
|
/* pvt switches. pbx stays the same, as does next */
|
||||||
|
|
||||||
@@ -891,10 +1058,12 @@ static int ast_do_masquerade(struct ast_channel *original)
|
|||||||
pthread_mutex_unlock(&clone->lock);
|
pthread_mutex_unlock(&clone->lock);
|
||||||
}
|
}
|
||||||
/* Set the write format */
|
/* Set the write format */
|
||||||
ast_set_write_format(original, original->writeformat);
|
ast_set_write_format(original, wformat);
|
||||||
|
|
||||||
/* Set the read format */
|
/* Set the read format */
|
||||||
ast_set_read_format(original, original->readformat);
|
ast_set_read_format(original, rformat);
|
||||||
|
|
||||||
|
ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat);
|
||||||
|
|
||||||
/* Okay. Last thing is to let the channel driver know about all this mess, so he
|
/* Okay. Last thing is to let the channel driver know about all this mess, so he
|
||||||
can fix up everything as best as possible */
|
can fix up everything as best as possible */
|
||||||
@@ -908,10 +1077,11 @@ static int ast_do_masquerade(struct ast_channel *original)
|
|||||||
} else
|
} else
|
||||||
ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)! Bad things may happen.\n",
|
ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)! Bad things may happen.\n",
|
||||||
original->type, original->name);
|
original->type, original->name);
|
||||||
|
|
||||||
/* Signal any blocker */
|
/* Signal any blocker */
|
||||||
if (original->blocking)
|
if (original->blocking)
|
||||||
pthread_kill(original->blocker, SIGURG);
|
pthread_kill(original->blocker, SIGURG);
|
||||||
|
ast_log(LOG_DEBUG, "Done Masquerading %s(%d) into the structure of %s(%d)\n",
|
||||||
|
clone->name, clone->state, original->name, original->state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -922,8 +1092,9 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
|
|||||||
struct ast_channel *cs[3];
|
struct ast_channel *cs[3];
|
||||||
int to = -1;
|
int to = -1;
|
||||||
struct ast_frame *f;
|
struct ast_frame *f;
|
||||||
struct ast_channel *who;
|
struct ast_channel *who = NULL;
|
||||||
int res;
|
int res;
|
||||||
|
int nativefailed=0;
|
||||||
/* Stop if we're a zombie or need a soft hangup */
|
/* Stop if we're a zombie or need a soft hangup */
|
||||||
if (c0->zombie || c0->softhangup || c1->zombie || c1->softhangup)
|
if (c0->zombie || c0->softhangup || c1->zombie || c1->softhangup)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -941,24 +1112,38 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
|
|||||||
/* Keep track of bridge */
|
/* Keep track of bridge */
|
||||||
c0->bridge = c1;
|
c0->bridge = c1;
|
||||||
c1->bridge = c0;
|
c1->bridge = c0;
|
||||||
|
cs[0] = c0;
|
||||||
|
cs[1] = c1;
|
||||||
|
for (/* ever */;;) {
|
||||||
|
/* Stop if we're a zombie or need a soft hangup */
|
||||||
|
if (c0->zombie || c0->softhangup || c1->zombie || c1->softhangup) {
|
||||||
|
*fo = NULL;
|
||||||
|
if (who) *rc = who;
|
||||||
|
res = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (c0->pvt->bridge &&
|
if (c0->pvt->bridge &&
|
||||||
(c0->pvt->bridge == c1->pvt->bridge)) {
|
(c0->pvt->bridge == c1->pvt->bridge) && !nativefailed) {
|
||||||
/* Looks like they share a bridge code */
|
/* Looks like they share a bridge code */
|
||||||
if (!c0->pvt->bridge(c0, c1, flags, fo, rc)) {
|
if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
|
||||||
c0->bridge = NULL;
|
c0->bridge = NULL;
|
||||||
c1->bridge = NULL;
|
c1->bridge = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* If they return non-zero then continue on normally. Let "-2" mean don't worry about
|
||||||
|
my not wanting to bridge */
|
||||||
|
if ((res != -2) && (res != -3))
|
||||||
ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
|
ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
|
||||||
/* If they return non-zero then continue on normally */
|
if (res != -3) nativefailed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat)) {
|
||||||
cs[0] = c0;
|
if (ast_channel_make_compatible(c0, c1)) {
|
||||||
cs[1] = c1;
|
ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
|
||||||
for (/* ever */;;) {
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
who = ast_waitfor_n(cs, 2, &to);
|
who = ast_waitfor_n(cs, 2, &to);
|
||||||
if (!who) {
|
if (!who) {
|
||||||
ast_log(LOG_WARNING, "Nobody there??\n");
|
ast_log(LOG_WARNING, "Nobody there??\n");
|
||||||
|
@@ -27,7 +27,7 @@ extern "C" {
|
|||||||
|
|
||||||
#ifdef DEBUG_THREADS
|
#ifdef DEBUG_THREADS
|
||||||
|
|
||||||
#define TRIES 500
|
#define TRIES 50
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -136,6 +136,9 @@ struct ast_channel {
|
|||||||
char exten[AST_MAX_EXTENSION]; /* Current extension number */
|
char exten[AST_MAX_EXTENSION]; /* Current extension number */
|
||||||
int priority; /* Current extension priority */
|
int priority; /* Current extension priority */
|
||||||
void *app[AST_CHANNEL_MAX_STACK]; /* Application information -- see assigned numbers */
|
void *app[AST_CHANNEL_MAX_STACK]; /* Application information -- see assigned numbers */
|
||||||
|
char dtmfq[AST_MAX_EXTENSION]; /* Any/all queued DTMF characters */
|
||||||
|
int deferdtmf; /* Are DTMF digits being deferred */
|
||||||
|
struct ast_frame dtmff; /* DTMF frame */
|
||||||
struct ast_channel_pvt *pvt;
|
struct ast_channel_pvt *pvt;
|
||||||
/* Private channel implementation details */
|
/* Private channel implementation details */
|
||||||
jmp_buf jmp[AST_CHANNEL_MAX_STACK]; /* Jump buffer used for returning from applications */
|
jmp_buf jmp[AST_CHANNEL_MAX_STACK]; /* Jump buffer used for returning from applications */
|
||||||
@@ -202,6 +205,12 @@ int ast_indicate(struct ast_channel *chan, int condition);
|
|||||||
Returns < 0 on failure, 0 if nothing ever arrived, and the # of ms remaining otherwise */
|
Returns < 0 on failure, 0 if nothing ever arrived, and the # of ms remaining otherwise */
|
||||||
int ast_waitfor(struct ast_channel *chan, int ms);
|
int ast_waitfor(struct ast_channel *chan, int ms);
|
||||||
|
|
||||||
|
/* Big momma function here. Wait for activity on any of the n channels, or any of the nfds
|
||||||
|
file descriptors. Returns the channel with activity, or NULL on error or if an FD
|
||||||
|
came first. If the FD came first, it will be returned in outfd, otherwise, outfd
|
||||||
|
will be -1 */
|
||||||
|
struct ast_channel *ast_waitfor_nandfds(struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms);
|
||||||
|
|
||||||
/* Wait for input on an array of channels for a given # of milliseconds. Return channel
|
/* Wait for input on an array of channels for a given # of milliseconds. Return channel
|
||||||
with activity, or NULL if none has activity. time "ms" is modified in-place, if applicable */
|
with activity, or NULL if none has activity. time "ms" is modified in-place, if applicable */
|
||||||
|
|
||||||
@@ -235,7 +244,8 @@ char ast_waitfordigit(struct ast_channel *c, int ms);
|
|||||||
|
|
||||||
/* Read in a digit string "s", max length "len", maximum timeout between
|
/* Read in a digit string "s", max length "len", maximum timeout between
|
||||||
digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout
|
digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout
|
||||||
for the first digit */
|
for the first digit. Returns 0 on normal return, or 1 on a timeout. In the case of
|
||||||
|
a timeout, any digits that were read before the timeout will still be available in s. */
|
||||||
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
|
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
|
||||||
|
|
||||||
#define AST_BRIDGE_DTMF_CHANNEL_0 (1 << 0) /* Report DTMF on channel 0 */
|
#define AST_BRIDGE_DTMF_CHANNEL_0 (1 << 0) /* Report DTMF on channel 0 */
|
||||||
@@ -275,6 +285,23 @@ int ast_channel_setoption(struct ast_channel *channel, int option, void *data, i
|
|||||||
/* Query the value of an option, optionally blocking until a reply is received */
|
/* Query the value of an option, optionally blocking until a reply is received */
|
||||||
struct ast_frame *ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block);
|
struct ast_frame *ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block);
|
||||||
|
|
||||||
|
/* Returns 0 if channel does not support HTML or non-zero if it does */
|
||||||
|
int ast_channel_supports_html(struct ast_channel *channel);
|
||||||
|
|
||||||
|
/* Send HTML or URL on link. Returns 0 on success or -1 on failure */
|
||||||
|
int ast_channel_sendhtml(struct ast_channel *channel, int subclass, char *data, int datalen);
|
||||||
|
|
||||||
|
/* Send URL on link. Returns 0 on success or -1 on failure */
|
||||||
|
int ast_channel_sendurl(struct ast_channel *channel, char *url);
|
||||||
|
|
||||||
|
/* Defer DTMF so that you only read things like hangups and audio. Returns
|
||||||
|
non-zero if channel was already DTMF-deferred or 0 if channel is just now
|
||||||
|
being DTMF-deferred */
|
||||||
|
int ast_channel_defer_dtmf(struct ast_channel *chan);
|
||||||
|
|
||||||
|
/* Undo defer. ast_read will return any dtmf characters that were queued */
|
||||||
|
void ast_channel_undefer_dtmf(struct ast_channel *chan);
|
||||||
|
|
||||||
#ifdef DO_CRASH
|
#ifdef DO_CRASH
|
||||||
#define CRASH do { *((int *)0) = 0; } while(0)
|
#define CRASH do { *((int *)0) = 0; } while(0)
|
||||||
#else
|
#else
|
||||||
|
@@ -30,6 +30,30 @@ extern "C" {
|
|||||||
#define AST_PBX_KEEPALIVE 10 /* Destroy the thread, but don't hang up the channel */
|
#define AST_PBX_KEEPALIVE 10 /* Destroy the thread, but don't hang up the channel */
|
||||||
|
|
||||||
struct ast_context;
|
struct ast_context;
|
||||||
|
struct ast_exten;
|
||||||
|
struct ast_include;
|
||||||
|
struct ast_ignorepat;
|
||||||
|
struct ast_sw;
|
||||||
|
|
||||||
|
struct ast_switch {
|
||||||
|
struct ast_switch *next; /* NULL */
|
||||||
|
char *name; /* Name of the switch */
|
||||||
|
char *description; /* Description of the switch */
|
||||||
|
int (*exists)(struct ast_channel *chan, char *context, char *exten, int priority, char *callerid, char *data);
|
||||||
|
int (*canmatch)(struct ast_channel *chan, char *context, char *exten, int priority, char *callerid, char *data);
|
||||||
|
int (*exec)(struct ast_channel *chan, char *context, char *exten, int priority, char *callerid, int newstack, char *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Register an alternative switch */
|
||||||
|
extern int ast_register_switch(struct ast_switch *sw);
|
||||||
|
|
||||||
|
/* Unregister an alternative switch */
|
||||||
|
extern void ast_unregister_switch(struct ast_switch *sw);
|
||||||
|
|
||||||
|
/* Look up an application */
|
||||||
|
extern struct ast_app *pbx_findapp(char *app);
|
||||||
|
|
||||||
|
int pbx_exec(struct ast_channel *c, struct ast_app *app, void *data, int newstack);
|
||||||
|
|
||||||
/* Register a new context */
|
/* Register a new context */
|
||||||
struct ast_context *ast_context_create(char *name, char *registrar);
|
struct ast_context *ast_context_create(char *name, char *registrar);
|
||||||
@@ -47,9 +71,15 @@ int ast_pbx_start(struct ast_channel *c);
|
|||||||
/* Execute the PBX in the current thread */
|
/* Execute the PBX in the current thread */
|
||||||
int ast_pbx_run(struct ast_channel *c);
|
int ast_pbx_run(struct ast_channel *c);
|
||||||
|
|
||||||
/* Add an extension to an extension context, this time with an ast_context * */
|
/* Add and extension to an extension context. Callerid is a pattern to match CallerID, or NULL to match any
|
||||||
|
callerid */
|
||||||
|
int ast_add_extension(char *context, int replace, char *extension, int priority, char *callerid,
|
||||||
|
char *application, void *data, void (*datad)(void *), char *registrar);
|
||||||
|
|
||||||
|
/* Add an extension to an extension context, this time with an ast_context *. CallerID is a pattern to match
|
||||||
|
on callerid, or NULL to not care about callerid */
|
||||||
int ast_add_extension2(struct ast_context *con,
|
int ast_add_extension2(struct ast_context *con,
|
||||||
int replace, char *extension, int priority,
|
int replace, char *extension, int priority, char *callerid,
|
||||||
char *application, void *data, void (*datad)(void *),
|
char *application, void *data, void (*datad)(void *),
|
||||||
char *registrar);
|
char *registrar);
|
||||||
|
|
||||||
@@ -64,25 +94,23 @@ int ast_register_application(char *app, int (*execute)(struct ast_channel *, voi
|
|||||||
int ast_unregister_application(char *app);
|
int ast_unregister_application(char *app);
|
||||||
|
|
||||||
/* If an extension exists, return non-zero */
|
/* If an extension exists, return non-zero */
|
||||||
int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority);
|
int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid);
|
||||||
|
|
||||||
/* If "exten" *could be* a valid extension in this context with or without
|
/* If "exten" *could be* a valid extension in this context with or without
|
||||||
some more digits, return non-zero. Basically, when this returns 0, no matter
|
some more digits, return non-zero. Basically, when this returns 0, no matter
|
||||||
what you add to exten, it's not going to be a valid extension anymore */
|
what you add to exten, it's not going to be a valid extension anymore */
|
||||||
int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority);
|
int ast_canmatch_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid);
|
||||||
|
|
||||||
/* Determine if a given extension matches a given pattern (in NXX format) */
|
/* Determine if a given extension matches a given pattern (in NXX format) */
|
||||||
int ast_extension_match(char *pattern, char *extension);
|
int ast_extension_match(char *pattern, char *extension);
|
||||||
|
|
||||||
/* Launch a new extension (i.e. new stack) */
|
/* Launch a new extension (i.e. new stack) */
|
||||||
int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority);
|
int ast_spawn_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid);
|
||||||
|
|
||||||
/* Execute an extension. If it's not available, do whatever you should do for
|
/* Execute an extension. If it's not available, do whatever you should do for
|
||||||
default extensions and halt the thread if necessary. This function does not
|
default extensions and halt the thread if necessary. This function does not
|
||||||
return, except on error. */
|
return, except on error. */
|
||||||
int ast_exec_extension(struct ast_channel *c, char *context, char *exten, int priority);
|
int ast_exec_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid);
|
||||||
/* Longest extension */
|
|
||||||
int ast_pbx_longest_extension(char *context);
|
|
||||||
|
|
||||||
/* Add an include */
|
/* Add an include */
|
||||||
int ast_context_add_include(char *context, char *include, char *registrar);
|
int ast_context_add_include(char *context, char *include, char *registrar);
|
||||||
@@ -92,6 +120,70 @@ int ast_context_add_include2(struct ast_context *con, char *include, char *regis
|
|||||||
int ast_context_remove_include(char *context, char *include, char *registrar);
|
int ast_context_remove_include(char *context, char *include, char *registrar);
|
||||||
int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar);
|
int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar);
|
||||||
|
|
||||||
|
/* Add a switch */
|
||||||
|
int ast_context_add_switch(char *context, char *sw, char *data, char *registrar);
|
||||||
|
int ast_context_add_switch2(struct ast_context *con, char *sw, char *data, char *registrar);
|
||||||
|
|
||||||
|
/* Remove a switch */
|
||||||
|
int ast_context_remove_switch(char *context, char *sw, char *data, char *registrar);
|
||||||
|
int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, char *registrar);
|
||||||
|
|
||||||
|
/* Simply remove extension from context */
|
||||||
|
int ast_context_remove_extension(char *context, char *extension, int priority,
|
||||||
|
char *registrar);
|
||||||
|
int ast_context_remove_extension2(struct ast_context *con, char *extension,
|
||||||
|
int priority, char *registrar);
|
||||||
|
|
||||||
|
/* Add an ignorepat */
|
||||||
|
int ast_context_add_ignorepat(char *context, char *ignorepat, char *registrar);
|
||||||
|
int ast_context_add_ignorepat2(struct ast_context *con, char *ignorepat, char *registrar);
|
||||||
|
|
||||||
|
/* Remove an ignorepat */
|
||||||
|
int ast_context_remove_ignorepat(char *context, char *ignorepat, char *registrar);
|
||||||
|
int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char *registrar);
|
||||||
|
|
||||||
|
/* Check if a number should be ignored with respect to dialtone cancellation. Returns 0 if
|
||||||
|
the pattern should not be ignored, or non-zero if the pattern should be ignored */
|
||||||
|
int ast_ignore_pattern(char *context, char *pattern);
|
||||||
|
|
||||||
|
/* Locking functions for outer modules, especially for completion functions */
|
||||||
|
int ast_lock_contexts(void);
|
||||||
|
int ast_unlock_contexts(void);
|
||||||
|
|
||||||
|
int ast_lock_context(struct ast_context *con);
|
||||||
|
int ast_unlock_context(struct ast_context *con);
|
||||||
|
|
||||||
|
/* Functions for returning values from structures */
|
||||||
|
char *ast_get_context_name(struct ast_context *con);
|
||||||
|
char *ast_get_extension_name(struct ast_exten *exten);
|
||||||
|
char *ast_get_include_name(struct ast_include *include);
|
||||||
|
char *ast_get_ignorepat_name(struct ast_ignorepat *ip);
|
||||||
|
char *ast_get_switch_name(struct ast_sw *sw);
|
||||||
|
char *ast_get_switch_data(struct ast_sw *sw);
|
||||||
|
|
||||||
|
/* Other extension stuff */
|
||||||
|
int ast_get_extension_priority(struct ast_exten *exten);
|
||||||
|
char *ast_get_extension_app(struct ast_exten *e);
|
||||||
|
void *ast_get_extension_app_data(struct ast_exten *e);
|
||||||
|
|
||||||
|
/* Registrar info functions ... */
|
||||||
|
char *ast_get_context_registrar(struct ast_context *c);
|
||||||
|
char *ast_get_extension_registrar(struct ast_exten *e);
|
||||||
|
char *ast_get_include_registrar(struct ast_include *i);
|
||||||
|
char *ast_get_ignorepat_registrar(struct ast_ignorepat *ip);
|
||||||
|
char *ast_get_switch_registrar(struct ast_sw *sw);
|
||||||
|
|
||||||
|
/* Walking functions ... */
|
||||||
|
struct ast_context *ast_walk_contexts(struct ast_context *con);
|
||||||
|
struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
|
||||||
|
struct ast_exten *priority);
|
||||||
|
struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
|
||||||
|
struct ast_exten *priority);
|
||||||
|
struct ast_include *ast_walk_context_includes(struct ast_context *con,
|
||||||
|
struct ast_include *inc);
|
||||||
|
struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
|
||||||
|
struct ast_ignorepat *ip);
|
||||||
|
struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw);
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user