Add support for parking with IAX2
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2318 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
534e78b372
commit
806bb3c63f
20
channel.c
20
channel.c
|
@ -597,8 +597,6 @@ int ast_softhangup(struct ast_channel *chan, int cause)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ast_do_masquerade(struct ast_channel *original);
|
|
||||||
|
|
||||||
static void free_translation(struct ast_channel *clone)
|
static void free_translation(struct ast_channel *clone)
|
||||||
{
|
{
|
||||||
if (clone->pvt->writetrans)
|
if (clone->pvt->writetrans)
|
||||||
|
@ -618,7 +616,7 @@ int ast_hangup(struct ast_channel *chan)
|
||||||
if someone is going to masquerade as us */
|
if someone is going to masquerade as us */
|
||||||
ast_mutex_lock(&chan->lock);
|
ast_mutex_lock(&chan->lock);
|
||||||
if (chan->masq) {
|
if (chan->masq) {
|
||||||
if (ast_do_masquerade(chan))
|
if (ast_do_masquerade(chan, 1))
|
||||||
ast_log(LOG_WARNING, "Failed to perform masquerade\n");
|
ast_log(LOG_WARNING, "Failed to perform masquerade\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,7 +819,7 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
|
||||||
for (x=0;x<n;x++) {
|
for (x=0;x<n;x++) {
|
||||||
ast_mutex_lock(&c[x]->lock);
|
ast_mutex_lock(&c[x]->lock);
|
||||||
if (c[x]->masq) {
|
if (c[x]->masq) {
|
||||||
if (ast_do_masquerade(c[x])) {
|
if (ast_do_masquerade(c[x], 1)) {
|
||||||
ast_log(LOG_WARNING, "Masquerade failed\n");
|
ast_log(LOG_WARNING, "Masquerade failed\n");
|
||||||
*ms = -1;
|
*ms = -1;
|
||||||
ast_mutex_unlock(&c[x]->lock);
|
ast_mutex_unlock(&c[x]->lock);
|
||||||
|
@ -1008,7 +1006,7 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
||||||
|
|
||||||
ast_mutex_lock(&chan->lock);
|
ast_mutex_lock(&chan->lock);
|
||||||
if (chan->masq) {
|
if (chan->masq) {
|
||||||
if (ast_do_masquerade(chan)) {
|
if (ast_do_masquerade(chan, 1)) {
|
||||||
ast_log(LOG_WARNING, "Failed to perform masquerade\n");
|
ast_log(LOG_WARNING, "Failed to perform masquerade\n");
|
||||||
f = NULL;
|
f = NULL;
|
||||||
} else
|
} else
|
||||||
|
@ -1343,7 +1341,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
||||||
}
|
}
|
||||||
/* Handle any pending masquerades */
|
/* Handle any pending masquerades */
|
||||||
if (chan->masq) {
|
if (chan->masq) {
|
||||||
if (ast_do_masquerade(chan)) {
|
if (ast_do_masquerade(chan, 1)) {
|
||||||
ast_log(LOG_WARNING, "Failed to perform masquerade\n");
|
ast_log(LOG_WARNING, "Failed to perform masquerade\n");
|
||||||
ast_mutex_unlock(&chan->lock);
|
ast_mutex_unlock(&chan->lock);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1926,7 +1924,7 @@ void ast_change_name(struct ast_channel *chan, char *newname)
|
||||||
manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid);
|
manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ast_do_masquerade(struct ast_channel *original)
|
int ast_do_masquerade(struct ast_channel *original, int needlock)
|
||||||
{
|
{
|
||||||
int x,i;
|
int x,i;
|
||||||
int res=0;
|
int res=0;
|
||||||
|
@ -1951,6 +1949,7 @@ static int ast_do_masquerade(struct ast_channel *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 */
|
||||||
|
|
||||||
|
if (needlock)
|
||||||
/* We need the clone's lock, too */
|
/* We need the clone's lock, too */
|
||||||
ast_mutex_lock(&clone->lock);
|
ast_mutex_lock(&clone->lock);
|
||||||
|
|
||||||
|
@ -2013,7 +2012,7 @@ static int ast_do_masquerade(struct ast_channel *original)
|
||||||
|
|
||||||
|
|
||||||
if (clone->pvt->fixup){
|
if (clone->pvt->fixup){
|
||||||
res = clone->pvt->fixup(original, clone);
|
res = clone->pvt->fixup(original, clone, needlock);
|
||||||
if (res)
|
if (res)
|
||||||
ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
|
ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
|
||||||
}
|
}
|
||||||
|
@ -2023,6 +2022,7 @@ static int ast_do_masquerade(struct ast_channel *original)
|
||||||
res = clone->pvt->hangup(clone);
|
res = clone->pvt->hangup(clone);
|
||||||
if (res) {
|
if (res) {
|
||||||
ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n");
|
ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n");
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&clone->lock);
|
ast_mutex_unlock(&clone->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2100,7 +2100,7 @@ static int ast_do_masquerade(struct ast_channel *original)
|
||||||
/* 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 */
|
||||||
if (original->pvt->fixup) {
|
if (original->pvt->fixup) {
|
||||||
res = original->pvt->fixup(clone, original);
|
res = original->pvt->fixup(clone, original, needlock);
|
||||||
if (res) {
|
if (res) {
|
||||||
ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n",
|
ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n",
|
||||||
original->type, original->name);
|
original->type, original->name);
|
||||||
|
@ -2115,12 +2115,14 @@ static int ast_do_masquerade(struct ast_channel *original)
|
||||||
zombie, then free it now (since it already is considered invalid). */
|
zombie, then free it now (since it already is considered invalid). */
|
||||||
if (clone->zombie) {
|
if (clone->zombie) {
|
||||||
ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name);
|
ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name);
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&clone->lock);
|
ast_mutex_unlock(&clone->lock);
|
||||||
ast_channel_free(clone);
|
ast_channel_free(clone);
|
||||||
manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
|
manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
|
||||||
} else {
|
} else {
|
||||||
ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name);
|
ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name);
|
||||||
clone->zombie=1;
|
clone->zombie=1;
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&clone->lock);
|
ast_mutex_unlock(&clone->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -380,9 +380,10 @@ static int agent_write(struct ast_channel *ast, struct ast_frame *f)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct agent_pvt *p = newchan->pvt->pvt;
|
struct agent_pvt *p = newchan->pvt->pvt;
|
||||||
|
if (needlock)
|
||||||
ast_mutex_lock(&p->lock);
|
ast_mutex_lock(&p->lock);
|
||||||
if (p->owner != oldchan) {
|
if (p->owner != oldchan) {
|
||||||
ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
|
ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
|
||||||
|
@ -390,6 +391,7 @@ static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p->owner = newchan;
|
p->owner = newchan;
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&p->lock);
|
ast_mutex_unlock(&p->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -755,7 +755,7 @@ static struct ast_frame *alsa_read(struct ast_channel *chan)
|
||||||
return &f;
|
return &f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct chan_alsa_pvt *p = newchan->pvt->pvt;
|
struct chan_alsa_pvt *p = newchan->pvt->pvt;
|
||||||
p->owner = newchan;
|
p->owner = newchan;
|
||||||
|
|
|
@ -623,16 +623,18 @@ static int oh323_indicate(struct ast_channel *c, int condition)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: WTF is this? Do I need this???
|
// FIXME: WTF is this? Do I need this???
|
||||||
static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct oh323_pvt *p = newchan->pvt->pvt;
|
struct oh323_pvt *p = newchan->pvt->pvt;
|
||||||
|
|
||||||
|
if (needlock)
|
||||||
ast_mutex_lock(&p->lock);
|
ast_mutex_lock(&p->lock);
|
||||||
if (p->owner != oldchan) {
|
if (p->owner != oldchan) {
|
||||||
ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
|
ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p->owner = newchan;
|
p->owner = newchan;
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&p->lock);
|
ast_mutex_unlock(&p->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1515,7 +1515,7 @@ static int iax_sendhtml(struct ast_channel *c, int subclass, char *data, int dat
|
||||||
return send_command(c->pvt->pvt, AST_FRAME_HTML, subclass, 0, data, datalen, -1);
|
return send_command(c->pvt->pvt, AST_FRAME_HTML, subclass, 0, data, datalen, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iax_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan)
|
static int iax_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct chan_iax_pvt *pvt = newchan->pvt->pvt;
|
struct chan_iax_pvt *pvt = newchan->pvt->pvt;
|
||||||
pvt->owner = newchan;
|
pvt->owner = newchan;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <asterisk/app.h>
|
#include <asterisk/app.h>
|
||||||
#include <asterisk/astdb.h>
|
#include <asterisk/astdb.h>
|
||||||
#include <asterisk/musiconhold.h>
|
#include <asterisk/musiconhold.h>
|
||||||
|
#include <asterisk/parking.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
@ -1750,14 +1751,16 @@ static int iax2_sendhtml(struct ast_channel *c, int subclass, char *data, int da
|
||||||
return send_command_locked(PTR_TO_CALLNO(c->pvt->pvt), AST_FRAME_HTML, subclass, 0, data, datalen, -1);
|
return send_command_locked(PTR_TO_CALLNO(c->pvt->pvt), AST_FRAME_HTML, subclass, 0, data, datalen, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan)
|
static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan, int lock)
|
||||||
{
|
{
|
||||||
unsigned short callno = PTR_TO_CALLNO(newchan->pvt->pvt);
|
unsigned short callno = PTR_TO_CALLNO(newchan->pvt->pvt);
|
||||||
|
if (lock)
|
||||||
ast_mutex_lock(&iaxsl[callno]);
|
ast_mutex_lock(&iaxsl[callno]);
|
||||||
if (iaxs[callno])
|
if (iaxs[callno])
|
||||||
iaxs[callno]->owner = newchan;
|
iaxs[callno]->owner = newchan;
|
||||||
else
|
else
|
||||||
ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
|
ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
|
||||||
|
if (lock)
|
||||||
ast_mutex_unlock(&iaxsl[callno]);
|
ast_mutex_unlock(&iaxsl[callno]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4228,7 +4231,7 @@ static void dp_lookup(int callno, char *context, char *callednum, char *callerid
|
||||||
memset(&ied1, 0, sizeof(ied1));
|
memset(&ied1, 0, sizeof(ied1));
|
||||||
mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
|
mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
|
||||||
/* Must be started */
|
/* Must be started */
|
||||||
if (ast_exists_extension(NULL, context, callednum, 1, callerid)) {
|
if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
|
||||||
dpstatus = IAX_DPSTATUS_EXISTS;
|
dpstatus = IAX_DPSTATUS_EXISTS;
|
||||||
} else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
|
} else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
|
||||||
dpstatus = IAX_DPSTATUS_CANEXIST;
|
dpstatus = IAX_DPSTATUS_CANEXIST;
|
||||||
|
@ -4281,6 +4284,84 @@ static void spawn_dp_lookup(int callno, char *context, char *callednum, char *ca
|
||||||
ast_log(LOG_WARNING, "Out of memory!\n");
|
ast_log(LOG_WARNING, "Out of memory!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct iax_dual {
|
||||||
|
struct ast_channel *chan1;
|
||||||
|
struct ast_channel *chan2;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *iax_park_thread(void *stuff)
|
||||||
|
{
|
||||||
|
struct ast_channel *chan1, *chan2;
|
||||||
|
struct iax_dual *d;
|
||||||
|
struct ast_frame *f;
|
||||||
|
int ext;
|
||||||
|
int res;
|
||||||
|
d = stuff;
|
||||||
|
chan1 = d->chan1;
|
||||||
|
chan2 = d->chan2;
|
||||||
|
free(d);
|
||||||
|
f = ast_read(chan1);
|
||||||
|
if (f)
|
||||||
|
ast_frfree(f);
|
||||||
|
res = ast_park_call(chan1, chan2, 0, &ext);
|
||||||
|
ast_hangup(chan2);
|
||||||
|
ast_log(LOG_DEBUG, "Parked on extension '%d'\n", ext);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iax_park(struct ast_channel *chan1, struct ast_channel *chan2)
|
||||||
|
{
|
||||||
|
struct iax_dual *d;
|
||||||
|
struct ast_channel *chan1m, *chan2m;
|
||||||
|
pthread_t th;
|
||||||
|
chan1m = ast_channel_alloc(0);
|
||||||
|
chan2m = ast_channel_alloc(0);
|
||||||
|
if (chan2m && chan1m) {
|
||||||
|
snprintf(chan1m->name, sizeof(chan1m->name), "Parking/%s", chan1->name);
|
||||||
|
/* Make formats okay */
|
||||||
|
chan1m->readformat = chan1->readformat;
|
||||||
|
chan1m->writeformat = chan1->writeformat;
|
||||||
|
ast_channel_masquerade(chan1m, chan1);
|
||||||
|
/* Setup the extensions and such */
|
||||||
|
strncpy(chan1m->context, chan1->context, sizeof(chan1m->context) - 1);
|
||||||
|
strncpy(chan1m->exten, chan1->exten, sizeof(chan1m->exten) - 1);
|
||||||
|
chan1m->priority = chan1->priority;
|
||||||
|
|
||||||
|
/* We make a clone of the peer channel too, so we can play
|
||||||
|
back the announcement */
|
||||||
|
snprintf(chan2m->name, sizeof (chan2m->name), "IAXPeer/%s",chan2->name);
|
||||||
|
/* Make formats okay */
|
||||||
|
chan2m->readformat = chan2->readformat;
|
||||||
|
chan2m->writeformat = chan2->writeformat;
|
||||||
|
ast_channel_masquerade(chan2m, chan2);
|
||||||
|
/* Setup the extensions and such */
|
||||||
|
strncpy(chan2m->context, chan2->context, sizeof(chan2m->context) - 1);
|
||||||
|
strncpy(chan2m->exten, chan2->exten, sizeof(chan2m->exten) - 1);
|
||||||
|
chan2m->priority = chan2->priority;
|
||||||
|
if (ast_do_masquerade(chan2m, 0)) {
|
||||||
|
ast_log(LOG_WARNING, "Masquerade failed :(\n");
|
||||||
|
ast_hangup(chan2m);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chan1m)
|
||||||
|
ast_hangup(chan1m);
|
||||||
|
if (chan2m)
|
||||||
|
ast_hangup(chan2m);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
d = malloc(sizeof(struct iax_dual));
|
||||||
|
if (d) {
|
||||||
|
memset(d, 0, sizeof(*d));
|
||||||
|
d->chan1 = chan1m;
|
||||||
|
d->chan2 = chan2m;
|
||||||
|
if (!pthread_create(&th, NULL, iax_park_thread, d))
|
||||||
|
return 0;
|
||||||
|
free(d);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int socket_read(int *id, int fd, short events, void *cbdata)
|
static int socket_read(int *id, int fd, short events, void *cbdata)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
|
@ -4799,12 +4880,19 @@ retryowner:
|
||||||
break;
|
break;
|
||||||
case IAX_COMMAND_TRANSFER:
|
case IAX_COMMAND_TRANSFER:
|
||||||
if (iaxs[fr.callno]->owner && iaxs[fr.callno]->owner->bridge && ies.called_number) {
|
if (iaxs[fr.callno]->owner && iaxs[fr.callno]->owner->bridge && ies.called_number) {
|
||||||
|
if (!strcmp(ies.called_number, ast_parking_ext())) {
|
||||||
|
if (iax_park(iaxs[fr.callno]->owner->bridge, iaxs[fr.callno]->owner)) {
|
||||||
|
ast_log(LOG_WARNING, "Failed to park call on '%s'\n", iaxs[fr.callno]->owner->bridge->name);
|
||||||
|
} else
|
||||||
|
ast_log(LOG_DEBUG, "Parked call on '%s'\n", iaxs[fr.callno]->owner->bridge->name);
|
||||||
|
} else {
|
||||||
if (ast_async_goto(iaxs[fr.callno]->owner->bridge, iaxs[fr.callno]->context, ies.called_number, 1, 1))
|
if (ast_async_goto(iaxs[fr.callno]->owner->bridge, iaxs[fr.callno]->context, ies.called_number, 1, 1))
|
||||||
ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", iaxs[fr.callno]->owner->bridge->name,
|
ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", iaxs[fr.callno]->owner->bridge->name,
|
||||||
ies.called_number, iaxs[fr.callno]->context);
|
ies.called_number, iaxs[fr.callno]->context);
|
||||||
else
|
else
|
||||||
ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", iaxs[fr.callno]->owner->bridge->name,
|
ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", iaxs[fr.callno]->owner->bridge->name,
|
||||||
ies.called_number, iaxs[fr.callno]->context);
|
ies.called_number, iaxs[fr.callno]->context);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr.callno);
|
ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr.callno);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -185,12 +185,14 @@ static int local_write(struct ast_channel *ast, struct ast_frame *f)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct local_pvt *p = newchan->pvt->pvt;
|
struct local_pvt *p = newchan->pvt->pvt;
|
||||||
|
if (needlock)
|
||||||
ast_mutex_lock(&p->lock);
|
ast_mutex_lock(&p->lock);
|
||||||
if ((p->owner != oldchan) && (p->chan != oldchan)) {
|
if ((p->owner != oldchan) && (p->chan != oldchan)) {
|
||||||
ast_log(LOG_WARNING, "old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
|
ast_log(LOG_WARNING, "old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&p->lock);
|
ast_mutex_unlock(&p->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -198,6 +200,7 @@ static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
||||||
p->owner = newchan;
|
p->owner = newchan;
|
||||||
else
|
else
|
||||||
p->chan = newchan;
|
p->chan = newchan;
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&p->lock);
|
ast_mutex_unlock(&p->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -771,7 +771,7 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct mgcp_subchannel *sub = newchan->pvt->pvt;
|
struct mgcp_subchannel *sub = newchan->pvt->pvt;
|
||||||
ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
|
ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
|
||||||
|
|
|
@ -661,7 +661,7 @@ static struct ast_frame *oss_read(struct ast_channel *chan)
|
||||||
return &f;
|
return &f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct chan_oss_pvt *p = newchan->pvt->pvt;
|
struct chan_oss_pvt *p = newchan->pvt->pvt;
|
||||||
p->owner = newchan;
|
p->owner = newchan;
|
||||||
|
|
|
@ -1364,16 +1364,19 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct sip_pvt *p = newchan->pvt->pvt;
|
struct sip_pvt *p = newchan->pvt->pvt;
|
||||||
|
if (needlock)
|
||||||
ast_mutex_lock(&p->lock);
|
ast_mutex_lock(&p->lock);
|
||||||
if (p->owner != oldchan) {
|
if (p->owner != oldchan) {
|
||||||
ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
|
ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&p->lock);
|
ast_mutex_unlock(&p->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p->owner = newchan;
|
p->owner = newchan;
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&p->lock);
|
ast_mutex_unlock(&p->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1650,7 +1650,7 @@ static int skinny_write(struct ast_channel *ast, struct ast_frame *frame)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct skinny_subchannel *sub = newchan->pvt->pvt;
|
struct skinny_subchannel *sub = newchan->pvt->pvt;
|
||||||
ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
|
ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
|
||||||
|
|
|
@ -651,7 +651,7 @@ static int vpb_indicate(struct ast_channel *ast, int condition)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct vpb_pvt *p = (struct vpb_pvt *)newchan->pvt->pvt;
|
struct vpb_pvt *p = (struct vpb_pvt *)newchan->pvt->pvt;
|
||||||
|
|
||||||
|
|
|
@ -2537,10 +2537,11 @@ static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
|
||||||
|
|
||||||
static int zt_indicate(struct ast_channel *chan, int condition);
|
static int zt_indicate(struct ast_channel *chan, int condition);
|
||||||
|
|
||||||
static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, int needlock)
|
||||||
{
|
{
|
||||||
struct zt_pvt *p = newchan->pvt->pvt;
|
struct zt_pvt *p = newchan->pvt->pvt;
|
||||||
int x;
|
int x;
|
||||||
|
if (needlock)
|
||||||
ast_mutex_lock(&p->lock);
|
ast_mutex_lock(&p->lock);
|
||||||
ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
|
ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
|
||||||
if (p->owner == oldchan)
|
if (p->owner == oldchan)
|
||||||
|
@ -2554,6 +2555,7 @@ static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
||||||
if (newchan->_state == AST_STATE_RINGING)
|
if (newchan->_state == AST_STATE_RINGING)
|
||||||
zt_indicate(newchan, AST_CONTROL_RINGING);
|
zt_indicate(newchan, AST_CONTROL_RINGING);
|
||||||
update_conf(p);
|
update_conf(p);
|
||||||
|
if (needlock)
|
||||||
ast_mutex_unlock(&p->lock);
|
ast_mutex_unlock(&p->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -777,6 +777,8 @@ int ast_settimeout(struct ast_channel *c, int samples, int (*func)(void *data),
|
||||||
and 1 if supported and requested */
|
and 1 if supported and requested */
|
||||||
int ast_transfer(struct ast_channel *chan, char *dest);
|
int ast_transfer(struct ast_channel *chan, char *dest);
|
||||||
|
|
||||||
|
int ast_do_masquerade(struct ast_channel *chan, int grablock);
|
||||||
|
|
||||||
/* Misc. functions below */
|
/* Misc. functions below */
|
||||||
|
|
||||||
//! Waits for activity on a group of channels
|
//! Waits for activity on a group of channels
|
||||||
|
|
|
@ -60,7 +60,7 @@ struct ast_channel_pvt {
|
||||||
/*! Indicate a particular condition (e.g. AST_CONTROL_BUSY or AST_CONTROL_RINGING or AST_CONTROL_CONGESTION */
|
/*! Indicate a particular condition (e.g. AST_CONTROL_BUSY or AST_CONTROL_RINGING or AST_CONTROL_CONGESTION */
|
||||||
int (*indicate)(struct ast_channel *c, int condition);
|
int (*indicate)(struct ast_channel *c, int condition);
|
||||||
/*! Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links */
|
/*! Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links */
|
||||||
int (*fixup)(struct ast_channel *oldchan, struct ast_channel *newchan);
|
int (*fixup)(struct ast_channel *oldchan, struct ast_channel *newchan, int lock);
|
||||||
/*! Set a given option */
|
/*! Set a given option */
|
||||||
int (*setoption)(struct ast_channel *chan, int option, void *data, int datalen);
|
int (*setoption)(struct ast_channel *chan, int option, void *data, int datalen);
|
||||||
/*! Query a given option */
|
/*! Query a given option */
|
||||||
|
|
Loading…
Reference in New Issue