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:
Mark Spencer 2004-03-04 01:11:25 +00:00
parent 534e78b372
commit 806bb3c63f
15 changed files with 152 additions and 48 deletions

View File

@ -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,8 +1949,9 @@ 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 */
/* We need the clone's lock, too */ if (needlock)
ast_mutex_lock(&clone->lock); /* We need the clone's lock, too */
ast_mutex_lock(&clone->lock);
ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock); ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &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,7 +2022,8 @@ 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");
ast_mutex_unlock(&clone->lock); if (needlock)
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,13 +2115,15 @@ 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);
ast_mutex_unlock(&clone->lock); if (needlock)
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;
ast_mutex_unlock(&clone->lock); if (needlock)
ast_mutex_unlock(&clone->lock);
} }
/* Signal any blocker */ /* Signal any blocker */

View File

@ -380,17 +380,19 @@ 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;
ast_mutex_lock(&p->lock); if (needlock)
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);
ast_mutex_unlock(&p->lock); ast_mutex_unlock(&p->lock);
return -1; return -1;
} }
p->owner = newchan; p->owner = newchan;
ast_mutex_unlock(&p->lock); if (needlock)
ast_mutex_unlock(&p->lock);
return 0; return 0;
} }

View File

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

View File

@ -623,17 +623,19 @@ 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;
ast_mutex_lock(&p->lock); if (needlock)
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;
ast_mutex_unlock(&p->lock); if (needlock)
ast_mutex_unlock(&p->lock);
return 0; return 0;
} }

View File

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

View File

@ -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,15 +1751,17 @@ 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);
ast_mutex_lock(&iaxsl[callno]); if (lock)
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");
ast_mutex_unlock(&iaxsl[callno]); if (lock)
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 (ast_async_goto(iaxs[fr.callno]->owner->bridge, iaxs[fr.callno]->context, ies.called_number, 1, 1)) if (!strcmp(ies.called_number, ast_parking_ext())) {
ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", iaxs[fr.callno]->owner->bridge->name, if (iax_park(iaxs[fr.callno]->owner->bridge, iaxs[fr.callno]->owner)) {
ies.called_number, iaxs[fr.callno]->context); ast_log(LOG_WARNING, "Failed to park call on '%s'\n", iaxs[fr.callno]->owner->bridge->name);
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, "Parked call on '%s'\n", iaxs[fr.callno]->owner->bridge->name);
ies.called_number, iaxs[fr.callno]->context); } else {
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,
ies.called_number, iaxs[fr.callno]->context);
else
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);
}
} 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;

View File

@ -185,20 +185,23 @@ 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;
ast_mutex_lock(&p->lock); if (needlock)
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);
ast_mutex_unlock(&p->lock); if (needlock)
ast_mutex_unlock(&p->lock);
return -1; return -1;
} }
if (p->owner == oldchan) if (p->owner == oldchan)
p->owner = newchan; p->owner = newchan;
else else
p->chan = newchan; p->chan = newchan;
ast_mutex_unlock(&p->lock); if (needlock)
ast_mutex_unlock(&p->lock);
return 0; return 0;
} }

View File

@ -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);

View File

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

View File

@ -1364,17 +1364,20 @@ 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;
ast_mutex_lock(&p->lock); if (needlock)
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);
ast_mutex_unlock(&p->lock); if (needlock)
ast_mutex_unlock(&p->lock);
return -1; return -1;
} }
p->owner = newchan; p->owner = newchan;
ast_mutex_unlock(&p->lock); if (needlock)
ast_mutex_unlock(&p->lock);
return 0; return 0;
} }

View File

@ -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);

View File

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

View File

@ -2537,11 +2537,12 @@ 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;
ast_mutex_lock(&p->lock); if (needlock)
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)
p->owner = newchan; p->owner = newchan;
@ -2554,7 +2555,8 @@ 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);
ast_mutex_unlock(&p->lock); if (needlock)
ast_mutex_unlock(&p->lock);
return 0; return 0;
} }

View File

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

View File

@ -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 */