diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-10-23 12:19:47 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-10-23 12:19:47 +0000 |
commit | d3403a17ea03efc1df307fd0f4a90414b311b5dc (patch) | |
tree | 43e47efe6f89f32ec12ee1d4588a8315ce8a3fe3 | |
parent | 6ee0e0d925c21a2691bee34e5f960cdc8fc54594 (diff) |
First pass at making transfer work within agent (not tested, shouldn't break anything that currently worked)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@4061 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-x | channel.c | 29 | ||||
-rwxr-xr-x | channels/chan_agent.c | 24 | ||||
-rwxr-xr-x | channels/chan_iax2.c | 22 | ||||
-rwxr-xr-x | channels/chan_local.c | 16 | ||||
-rwxr-xr-x | channels/chan_mgcp.c | 67 | ||||
-rwxr-xr-x | channels/chan_oss.c | 8 | ||||
-rwxr-xr-x | channels/chan_sip.c | 46 | ||||
-rwxr-xr-x | channels/chan_skinny.c | 4 | ||||
-rwxr-xr-x | channels/chan_zap.c | 88 | ||||
-rwxr-xr-x | include/asterisk/channel.h | 8 | ||||
-rwxr-xr-x | include/asterisk/channel_pvt.h | 2 | ||||
-rwxr-xr-x | manager.c | 4 |
12 files changed, 176 insertions, 142 deletions
@@ -2479,6 +2479,15 @@ static long tvdiff(struct timeval *now, struct timeval *then) return (((now->tv_sec * 1000) + now->tv_usec / 1000) - ((then->tv_sec * 1000) + then->tv_usec / 1000)); } +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); + return bridged; +} + static void bridge_playfile(struct ast_channel *chan, struct ast_channel *peer, char *sound, int remain) { int res=0, min=0, sec=0,check=0; @@ -2552,20 +2561,20 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct as /* Stop if we're a zombie or need a soft hangup */ if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) return -1; - if (c0->bridge) { + if (c0->_bridge) { ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", - c0->name, c0->bridge->name); + c0->name, c0->_bridge->name); return -1; } - if (c1->bridge) { + if (c1->_bridge) { ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", - c1->name, c1->bridge->name); + c1->name, c1->_bridge->name); return -1; } /* Keep track of bridge */ - c0->bridge = c1; - c1->bridge = c0; + c0->_bridge = c1; + c1->_bridge = c0; cs[0] = c0; cs[1] = c1; @@ -2632,8 +2641,8 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct as 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, flags, fo, rc))) { - c0->bridge = NULL; - c1->bridge = NULL; + c0->_bridge = NULL; + c1->_bridge = NULL; manager_event(EVENT_FLAG_CALL, "Unlink", "Channel1: %s\r\n" "Channel2: %s\r\n" @@ -2737,8 +2746,8 @@ tackygoto: cs[0] = cs[1]; cs[1] = cs[2]; } - c0->bridge = NULL; - c1->bridge = NULL; + c0->_bridge = NULL; + c1->_bridge = NULL; manager_event(EVENT_FLAG_CALL, "Unlink", "Channel1: %s\r\n" "Channel2: %s\r\n" diff --git a/channels/chan_agent.c b/channels/chan_agent.c index 2246bf900..706f6754d 100755 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -324,6 +324,7 @@ static struct ast_frame *agent_read(struct ast_channel *ast) /* Note that we don't hangup if it's not a callback because Asterisk will do it for us when the PBX instance that called login finishes */ if (!ast_strlen_zero(p->loginchan)) { + p->chan->_bridge = NULL; ast_hangup(p->chan); if (p->wrapuptime) { gettimeofday(&p->lastdisc, NULL); @@ -351,6 +352,9 @@ static struct ast_frame *agent_read(struct ast_channel *ast) else { p->acknowledged = 1; f = &answer_frame; + if (p->chan) + p->chan->_bridge = ast; + } } if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) { @@ -360,6 +364,8 @@ static struct ast_frame *agent_read(struct ast_channel *ast) p->acknowledged = 1; ast_frfree(f); f = &answer_frame; + if (p->chan) + p->chan->_bridge = ast; } } if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { @@ -704,6 +710,19 @@ static int agent_ack_sleep( void *data ) return res; } +static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge) +{ + struct agent_pvt *p; + struct ast_channel *ret=NULL; + + p = bridge->pvt->pvt; + if (chan == p->chan) + ret = bridge->_bridge; + else if (chan == bridge->_bridge) + ret = p->chan; + return NULL; +} + static struct ast_channel *agent_new(struct agent_pvt *p, int state) { struct ast_channel *tmp; @@ -748,6 +767,7 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state) tmp->pvt->exception = agent_read; tmp->pvt->indicate = agent_indicate; tmp->pvt->fixup = agent_fixup; + tmp->pvt->bridged_channel = agent_bridgedchannel; p->owner = tmp; ast_mutex_lock(&usecnt_lock); usecnt++; @@ -1144,8 +1164,8 @@ static int agents_show(int fd, int argc, char **argv) username[0] = '\0'; if (p->chan) { snprintf(location, sizeof(location), "logged in on %s", p->chan->name); - if (p->owner && p->owner->bridge) { - snprintf(talkingto, sizeof(talkingto), " talking to %s", p->owner->bridge->name); + if (p->owner && ast_bridged_channel(p->owner)) { + snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name); } else { strncpy(talkingto, " is idle", sizeof(talkingto) - 1); } diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 3e995e8bd..d8b0b38dd 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -5366,8 +5366,8 @@ retryowner: iaxs[fr.callno]->quelch = 1; if (ies.musiconhold) { if (iaxs[fr.callno]->owner && - iaxs[fr.callno]->owner->bridge) - ast_moh_start(iaxs[fr.callno]->owner->bridge, NULL); + ast_bridged_channel(iaxs[fr.callno]->owner)) + ast_moh_start(ast_bridged_channel(iaxs[fr.callno]->owner), NULL); } } break; @@ -5375,8 +5375,8 @@ retryowner: if (iaxs[fr.callno]->state & IAX_STATE_STARTED) { iaxs[fr.callno]->quelch = 0; if (iaxs[fr.callno]->owner && - iaxs[fr.callno]->owner->bridge) - ast_moh_stop(iaxs[fr.callno]->owner->bridge); + ast_bridged_channel(iaxs[fr.callno]->owner)) + ast_moh_stop(ast_bridged_channel(iaxs[fr.callno]->owner)); } break; case IAX_COMMAND_TXACC: @@ -5522,18 +5522,18 @@ retryowner: iax2_destroy_nolock(fr.callno); break; case IAX_COMMAND_TRANSFER: - if (iaxs[fr.callno]->owner && iaxs[fr.callno]->owner->bridge && ies.called_number) { + if (iaxs[fr.callno]->owner && ast_bridged_channel(iaxs[fr.callno]->owner) && 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); + if (iax_park(ast_bridged_channel(iaxs[fr.callno]->owner), iaxs[fr.callno]->owner)) { + ast_log(LOG_WARNING, "Failed to park call on '%s'\n", ast_bridged_channel(iaxs[fr.callno]->owner)->name); } else - ast_log(LOG_DEBUG, "Parked call on '%s'\n", iaxs[fr.callno]->owner->bridge->name); + ast_log(LOG_DEBUG, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr.callno]->owner)->name); } else { - if (ast_async_goto(iaxs[fr.callno]->owner->bridge, iaxs[fr.callno]->context, ies.called_number, 1)) - ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", iaxs[fr.callno]->owner->bridge->name, + if (ast_async_goto(ast_bridged_channel(iaxs[fr.callno]->owner), iaxs[fr.callno]->context, ies.called_number, 1)) + ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", ast_bridged_channel(iaxs[fr.callno]->owner)->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, + ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", ast_bridged_channel(iaxs[fr.callno]->owner)->name, ies.called_number, iaxs[fr.callno]->context); } } else diff --git a/channels/chan_local.c b/channels/chan_local.c index 9d004b5ed..fa879d59d 100755 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -139,28 +139,28 @@ static void check_bridge(struct local_pvt *p, int isoutbound) { if (p->alreadymasqed || p->nooptimization) return; - if (isoutbound && p->chan && p->chan->bridge && p->owner) { + if (isoutbound && p->chan && ast_bridged_channel(p->chan) && p->owner) { /* Masquerade bridged channel into owner */ /* Lock everything we need, one by one, and give up if we can't get everything. Remember, we'll get another chance in just a little bit */ - if (!ast_mutex_trylock(&p->chan->bridge->lock)) { + if (!ast_mutex_trylock(&(ast_bridged_channel(p->chan))->lock)) { if (!ast_mutex_trylock(&p->owner->lock)) { - ast_channel_masquerade(p->owner, p->chan->bridge); + ast_channel_masquerade(p->owner, ast_bridged_channel(p->chan)); p->alreadymasqed = 1; ast_mutex_unlock(&p->owner->lock); } - ast_mutex_unlock(&p->chan->bridge->lock); + ast_mutex_unlock(&(ast_bridged_channel(p->chan)->lock)); } - } else if (!isoutbound && p->owner && p->owner->bridge && p->chan) { + } else if (!isoutbound && p->owner && ast_bridged_channel(p->owner) && p->chan) { /* Masquerade bridged channel into chan */ - if (!ast_mutex_trylock(&p->owner->bridge->lock)) { + if (!ast_mutex_trylock(&(ast_bridged_channel(p->owner)->lock))) { if (!ast_mutex_trylock(&p->chan->lock)) { - ast_channel_masquerade(p->chan, p->owner->bridge); + ast_channel_masquerade(p->chan, ast_bridged_channel(p->owner)); p->alreadymasqed = 1; ast_mutex_unlock(&p->chan->lock); } - ast_mutex_unlock(&p->owner->bridge->lock); + ast_mutex_unlock(&(ast_bridged_channel(p->owner)->lock)); } } } diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index fd4aff6a8..4db202e40 100755 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -898,16 +898,16 @@ static int mgcp_hangup(struct ast_channel *ast) sub->cxident[0] = '\0'; if ((sub == p->sub) && sub->next->owner) { if (p->hookstate == MGCP_OFFHOOK) { - if (sub->next->owner && sub->next->owner->bridge) { - transmit_notify_request_with_callerid(p->sub, "L/wt", sub->next->owner->bridge->cid.cid_num, sub->next->owner->bridge->cid.cid_name); + if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { + transmit_notify_request_with_callerid(p->sub, "L/wt", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name); } } else { /* set our other connection as the primary and swith over to it */ p->sub = sub->next; p->sub->cxmode = MGCP_CX_RECVONLY; transmit_modify_request(p->sub); - if (sub->next->owner && sub->next->owner->bridge) { - transmit_notify_request_with_callerid(p->sub, "L/rg", sub->next->owner->bridge->cid.cid_num, sub->next->owner->bridge->cid.cid_name); + if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { + transmit_notify_request_with_callerid(p->sub, "L/rg", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name); } } @@ -2606,10 +2606,10 @@ static void *mgcp_ss(void *data) len = 0; } else if (!strcmp(exten, ast_parking_ext()) && sub->next->owner && - sub->next->owner->bridge) { + ast_bridged_channel(sub->next->owner)) { /* This is a three way call, the main call being a real channel, and we're parking the first call. */ - ast_masq_park_call(sub->next->owner->bridge, chan, 0, NULL); + ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL); if (option_verbose > 2) { ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); } @@ -2707,29 +2707,29 @@ static int attempt_transfer(struct mgcp_endpoint *p) /* In order to transfer, we need at least one of the channels to actually be in a call bridge. We can't conference two applications together (but then, why would we want to?) */ - if (p->sub->owner->bridge) { + if (ast_bridged_channel(p->sub->owner)) { /* The three-way person we're about to transfer to could still be in MOH, so stop if now if appropriate */ - if (p->sub->next->owner->bridge) - ast_moh_stop(p->sub->next->owner->bridge); + if (ast_bridged_channel(p->sub->next->owner)) + ast_moh_stop(ast_bridged_channel(p->sub->next->owner)); if (p->sub->owner->_state == AST_STATE_RINGING) { - ast_indicate(p->sub->next->owner->bridge, AST_CONTROL_RINGING); + ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); } - if (ast_channel_masquerade(p->sub->next->owner, p->sub->owner->bridge)) { + if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) { ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", - p->sub->owner->bridge->name, p->sub->next->owner->name); + ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name); return -1; } /* Orphan the channel */ unalloc_sub(p->sub->next); - } else if (p->sub->next->owner->bridge) { + } else if (ast_bridged_channel(p->sub->next->owner)) { if (p->sub->owner->_state == AST_STATE_RINGING) { - ast_indicate(p->sub->next->owner->bridge, AST_CONTROL_RINGING); + ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); } - ast_moh_stop(p->sub->next->owner->bridge); - if (ast_channel_masquerade(p->sub->owner, p->sub->next->owner->bridge)) { + ast_moh_stop(ast_bridged_channel(p->sub->next->owner)); + if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) { ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", - p->sub->next->owner->bridge->name, p->sub->owner->name); + ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name); return -1; } /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/ @@ -2765,8 +2765,8 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev) if (sub->outgoing) { /* Answered */ if (sub->owner) { - if (sub->owner->bridge) { - ast_moh_stop(sub->owner->bridge); + if (ast_bridged_channel(sub->owner)) { + ast_moh_stop(ast_bridged_channel(sub->owner)); } sub->cxmode = MGCP_CX_SENDRECV; if (!sub->rtp) { @@ -2823,8 +2823,8 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev) ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?"); } - if (sub->owner->bridge) { - ast_moh_stop(sub->owner->bridge); + if (ast_bridged_channel(sub->owner)) { + ast_moh_stop(ast_bridged_channel(sub->owner)); } sub->cxmode = MGCP_CX_SENDRECV; if (!sub->rtp) { @@ -2948,8 +2948,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); } transmit_modify_request(sub); - if (sub->owner && sub->owner->bridge) { - ast_moh_start(sub->owner->bridge, NULL); + if (sub->owner && ast_bridged_channel(sub->owner)) { + ast_moh_start(ast_bridged_channel(sub->owner), NULL); } sub->next->cxmode = MGCP_CX_RECVONLY; handle_hd_hf(sub->next, ev); @@ -2963,9 +2963,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, } sub->cxmode = MGCP_CX_CONF; sub->next->cxmode = MGCP_CX_CONF; - if (sub->next->owner->bridge) { - ast_moh_stop(sub->next->owner->bridge); - } + if (ast_bridged_channel(sub->next->owner)) + ast_moh_stop(ast_bridged_channel(sub->next->owner)); transmit_modify_request(sub); transmit_modify_request(sub->next); } else { @@ -2981,12 +2980,12 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); } transmit_modify_request(sub); - if (sub->owner->bridge) { - ast_moh_start(sub->owner->bridge, NULL); - } - if (sub->next->owner->bridge) { - ast_moh_stop(sub->next->owner->bridge); - } + if (ast_bridged_channel(sub->owner)) + ast_moh_start(ast_bridged_channel(sub->owner), NULL); + + if (ast_bridged_channel(sub->next->owner)) + ast_moh_stop(ast_bridged_channel(sub->next->owner)); + handle_hd_hf(sub->next, ev); #if 0 if (sub->next->owner && (sub->next->owner->_state != AST_STATE_UP)) { @@ -3009,8 +3008,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, /* XXX - What do we do now? */ return -1; } - if (p->sub->owner->bridge) { - ast_moh_stop(p->sub->owner->bridge); + if (ast_bridged_channel(p->sub->owner)) { + ast_moh_stop(ast_bridged_channel(p->sub->owner)); } p->sub->cxmode = MGCP_CX_SENDRECV; transmit_modify_request(p->sub); diff --git a/channels/chan_oss.c b/channels/chan_oss.c index 61dd4ce89..c1d5ee0b3 100755 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -933,7 +933,7 @@ static int console_transfer(int fd, int argc, char *argv[]) char *context; if (argc != 2) return RESULT_SHOWUSAGE; - if (oss.owner && oss.owner->bridge) { + if (oss.owner && ast_bridged_channel(oss.owner)) { strncpy(tmp, argv[1], sizeof(tmp) - 1); context = strchr(tmp, '@'); if (context) { @@ -941,10 +941,10 @@ static int console_transfer(int fd, int argc, char *argv[]) context++; } else context = oss.owner->context; - if (ast_exists_extension(oss.owner->bridge, context, tmp, 1, oss.owner->bridge->cid.cid_num)) { + if (ast_exists_extension(ast_bridged_channel(oss.owner), context, tmp, 1, ast_bridged_channel(oss.owner)->cid.cid_num)) { ast_cli(fd, "Whee, transferring %s to %s@%s.\n", - oss.owner->bridge->name, tmp, context); - if (ast_async_goto(oss.owner->bridge, context, tmp, 1)) + ast_bridged_channel(oss.owner)->name, tmp, context); + if (ast_async_goto(ast_bridged_channel(oss.owner), context, tmp, 1)) ast_cli(fd, "Failed to transfer :(\n"); } else { ast_cli(fd, "No such extension exists\n"); diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 1531dd0ed..56acb1683 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2763,12 +2763,12 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req) ast_set_read_format(p->owner, p->owner->readformat); ast_set_write_format(p->owner, p->owner->writeformat); } - if (p->owner->bridge) { + if (ast_bridged_channel(p->owner)) { /* Turn on/off music on hold if we are holding/unholding */ if (sin.sin_addr.s_addr && !sendonly) { - ast_moh_stop(p->owner->bridge); + ast_moh_stop(ast_bridged_channel(p->owner)); } else { - ast_moh_start(p->owner->bridge, NULL); + ast_moh_start(ast_bridged_channel(p->owner), NULL); } } } @@ -6954,38 +6954,38 @@ static int attempt_transfer(struct sip_pvt *p1, struct sip_pvt *p2) ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n"); return -1; } - if (p1->owner->bridge) { - if (p2->owner->bridge) - ast_moh_stop(p2->owner->bridge); - ast_moh_stop(p1->owner->bridge); - ast_moh_stop(p1->owner); - ast_moh_stop(p2->owner); + if (ast_bridged_channel(p1->owner)) { + if (ast_bridged_channel(p2->owner)) + ast_moh_stop(ast_bridged_channel(p2->owner)); + ast_moh_stop(ast_bridged_channel(p1->owner)); + ast_moh_stop(ast_bridged_channel(p1->owner)); + ast_moh_stop(ast_bridged_channel(p2->owner)); if (p1->owner->cdr) { p2->owner->cdr = ast_cdr_append(p2->owner->cdr, p1->owner->cdr); p1->owner->cdr = NULL; } - if (p1->owner->bridge->cdr) { - p2->owner->cdr = ast_cdr_append(p2->owner->cdr, p1->owner->bridge->cdr); - p1->owner->bridge->cdr = NULL; + if (ast_bridged_channel(p1->owner)->cdr) { + p2->owner->cdr = ast_cdr_append(p2->owner->cdr, ast_bridged_channel(p1->owner)->cdr); + ast_bridged_channel(p1->owner)->cdr = NULL; } - if (ast_channel_masquerade(p2->owner, p1->owner->bridge)) { - ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", p2->owner->name, p1->owner->bridge->name); + if (ast_channel_masquerade(p2->owner, ast_bridged_channel(p1->owner))) { + ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", p2->owner->name, ast_bridged_channel(p1->owner)->name); return -1; } - } else if (p2->owner->bridge) { - ast_moh_stop(p2->owner->bridge); + } else if (ast_bridged_channel(p2->owner)) { + ast_moh_stop(ast_bridged_channel(p2->owner)); ast_moh_stop(p2->owner); ast_moh_stop(p1->owner); if (p2->owner->cdr) { p1->owner->cdr = ast_cdr_append(p1->owner->cdr, p2->owner->cdr); p2->owner->cdr = NULL; } - if (p2->owner->bridge->cdr) { - p1->owner->cdr = ast_cdr_append(p1->owner->cdr, p2->owner->bridge->cdr); - p2->owner->bridge->cdr = NULL; + if (ast_bridged_channel(p2->owner)->cdr) { + p1->owner->cdr = ast_cdr_append(p1->owner->cdr, ast_bridged_channel(p2->owner)->cdr); + ast_bridged_channel(p2->owner)->cdr = NULL; } - if (ast_channel_masquerade(p1->owner, p2->owner->bridge)) { - ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", p1->owner->name, p2->owner->bridge->name); + if (ast_channel_masquerade(p1->owner, ast_bridged_channel(p2->owner))) { + ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", p1->owner->name, ast_bridged_channel(p2->owner)->name); return -1; } } else { @@ -7303,7 +7303,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc ast_log(LOG_DEBUG,"202 Accepted (blind)\n"); c = p->owner; if (c) { - transfer_to = c->bridge; + transfer_to = ast_bridged_channel(c); if (transfer_to) { ast_moh_stop(transfer_to); if (!strcmp(p->refer_to, ast_parking_ext())) { @@ -7378,7 +7378,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc if (!res) { c = p->owner; if (c) { - transfer_to = c->bridge; + transfer_to = ast_bridged_channel(c); if (transfer_to) { /* Don't actually hangup here... */ ast_moh_stop(transfer_to); diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index 3a37ea213..a77c4b18f 100755 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -1407,10 +1407,10 @@ static void *skinny_ss(void *data) len = 0; } else if (!strcmp(exten, ast_parking_ext()) && sub->next->owner && - sub->next->owner->bridge) { + ast_bridged_channel(sub->next->owner)) { /* This is a three way call, the main call being a real channel, and we're parking the first call. */ - ast_masq_park_call(sub->next->owner->bridge, chan, 0, NULL); + ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL); if (option_verbose > 2) { ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); } diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 0855ab68e..ad9ba471e 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -2012,8 +2012,8 @@ static int zt_hangup(struct ast_channel *ast) p->owner = p->subs[SUB_REAL].owner; if (p->owner->_state != AST_STATE_UP) p->subs[SUB_REAL].needanswer = 1; - if (p->subs[SUB_REAL].owner->bridge) - ast_moh_stop(p->subs[SUB_REAL].owner->bridge); + if (ast_bridged_channel(p->subs[SUB_REAL].owner)) + ast_moh_stop(ast_bridged_channel(p->subs[SUB_REAL].owner)); } else if (p->subs[SUB_THREEWAY].zfd > -1) { swap_subs(p, SUB_THREEWAY, SUB_REAL); unalloc_sub(p, SUB_THREEWAY); @@ -2034,8 +2034,8 @@ static int zt_hangup(struct ast_channel *ast) if (p->subs[SUB_CALLWAIT].inthreeway) { /* This is actually part of a three way, placed on hold. Place the third part on music on hold now */ - if (p->subs[SUB_THREEWAY].owner && p->subs[SUB_THREEWAY].owner->bridge) - ast_moh_start(p->subs[SUB_THREEWAY].owner->bridge, NULL); + if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) + ast_moh_start(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), NULL); p->subs[SUB_THREEWAY].inthreeway = 0; /* Make it the call wait now */ swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); @@ -2046,8 +2046,8 @@ static int zt_hangup(struct ast_channel *ast) if (p->subs[SUB_CALLWAIT].inthreeway) { /* The other party of the three way call is currently in a call-wait state. Start music on hold for them, and take the main guy out of the third call */ - if (p->subs[SUB_CALLWAIT].owner && p->subs[SUB_CALLWAIT].owner->bridge) - ast_moh_start(p->subs[SUB_CALLWAIT].owner->bridge, NULL); + if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) + ast_moh_start(ast_bridged_channel(p->subs[SUB_CALLWAIT].owner), NULL); p->subs[SUB_CALLWAIT].inthreeway = 0; } p->subs[SUB_REAL].inthreeway = 0; @@ -2867,13 +2867,13 @@ static int attempt_transfer(struct zt_pvt *p) /* In order to transfer, we need at least one of the channels to actually be in a call bridge. We can't conference two applications together (but then, why would we want to?) */ - if (p->subs[SUB_REAL].owner->bridge) { + if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { /* The three-way person we're about to transfer to could still be in MOH, so stop if now if appropriate */ - if (p->subs[SUB_THREEWAY].owner->bridge) - ast_moh_stop(p->subs[SUB_THREEWAY].owner->bridge); + if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) + ast_moh_stop(ast_bridged_channel(p->subs[SUB_THREEWAY].owner)); if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { - ast_indicate(p->subs[SUB_REAL].owner->bridge, AST_CONTROL_RINGING); + ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); } if (p->subs[SUB_REAL].owner->cdr) { /* Move CDR from second channel to current one */ @@ -2881,40 +2881,40 @@ static int attempt_transfer(struct zt_pvt *p) ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->cdr); p->subs[SUB_REAL].owner->cdr = NULL; } - if (p->subs[SUB_REAL].owner->bridge->cdr) { + if (ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr) { /* Move CDR from second channel's bridge to current one */ p->subs[SUB_THREEWAY].owner->cdr = - ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->bridge->cdr); - p->subs[SUB_REAL].owner->bridge->cdr = NULL; + ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr); + ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr = NULL; } - if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, p->subs[SUB_REAL].owner->bridge)) { + if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", - p->subs[SUB_REAL].owner->bridge->name, p->subs[SUB_THREEWAY].owner->name); + ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); return -1; } /* Orphan the channel after releasing the lock */ ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); unalloc_sub(p, SUB_THREEWAY); - } else if (p->subs[SUB_THREEWAY].owner->bridge) { + } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { - ast_indicate(p->subs[SUB_THREEWAY].owner->bridge, AST_CONTROL_RINGING); + ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); } - ast_moh_stop(p->subs[SUB_THREEWAY].owner->bridge); + ast_moh_stop(ast_bridged_channel(p->subs[SUB_THREEWAY].owner)); if (p->subs[SUB_THREEWAY].owner->cdr) { /* Move CDR from second channel to current one */ p->subs[SUB_REAL].owner->cdr = ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->cdr); p->subs[SUB_THREEWAY].owner->cdr = NULL; } - if (p->subs[SUB_THREEWAY].owner->bridge->cdr) { + if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr) { /* Move CDR from second channel's bridge to current one */ p->subs[SUB_REAL].owner->cdr = - ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->bridge->cdr); - p->subs[SUB_THREEWAY].owner->bridge->cdr = NULL; + ast_cdr_append(p->subs[SUB_REAL].owner->cdr, ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr); + ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr = NULL; } - if (ast_channel_masquerade(p->subs[SUB_REAL].owner, p->subs[SUB_THREEWAY].owner->bridge)) { + if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", - p->subs[SUB_THREEWAY].owner->bridge->name, p->subs[SUB_REAL].owner->name); + ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); return -1; } /* Three-way is now the REAL */ @@ -3360,8 +3360,8 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) /* Make sure it stops ringing */ zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK); /* Okay -- probably call waiting*/ - if (p->owner->bridge) - ast_moh_stop(p->owner->bridge); + if (ast_bridged_channel(p->owner)) + ast_moh_stop(ast_bridged_channel(p->owner)); break; case AST_STATE_RESERVED: /* Start up dialtone */ @@ -3470,10 +3470,10 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) p->callwaitingrepeat = 0; p->cidcwexpire = 0; /* Start music on hold if appropriate */ - if (!p->subs[SUB_CALLWAIT].inthreeway && p->subs[SUB_CALLWAIT].owner->bridge) - ast_moh_start(p->subs[SUB_CALLWAIT].owner->bridge, NULL); - if (p->subs[SUB_REAL].owner->bridge) - ast_moh_stop(p->subs[SUB_REAL].owner->bridge); + if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) + ast_moh_start(ast_bridged_channel(p->subs[SUB_CALLWAIT].owner), NULL); + if (ast_bridged_channel(p->subs[SUB_REAL].owner)) + ast_moh_stop(ast_bridged_channel(p->subs[SUB_REAL].owner)); } else if (!p->subs[SUB_THREEWAY].owner) { char cid_num[256]=""; char cid_name[256]=""; @@ -3527,8 +3527,8 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel); /* Start music on hold if appropriate */ - if (p->subs[SUB_THREEWAY].owner->bridge) - ast_moh_start(p->subs[SUB_THREEWAY].owner->bridge, NULL); + if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) + ast_moh_start(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), NULL); } } else ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); @@ -3567,8 +3567,8 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) swap_subs(p, SUB_THREEWAY, SUB_REAL); otherindex = SUB_REAL; } - if (p->subs[otherindex].owner && p->subs[otherindex].owner->bridge) - ast_moh_stop(p->subs[otherindex].owner->bridge); + if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) + ast_moh_stop(ast_bridged_channel(p->subs[otherindex].owner)); p->owner = p->subs[SUB_REAL].owner; if (ast->_state == AST_STATE_RINGING) { ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n"); @@ -3581,8 +3581,8 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) swap_subs(p, SUB_THREEWAY, SUB_REAL); p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; p->owner = p->subs[SUB_REAL].owner; - if (p->subs[SUB_REAL].owner && p->subs[SUB_REAL].owner->bridge) - ast_moh_stop(p->subs[SUB_REAL].owner->bridge); + if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) + ast_moh_stop(ast_bridged_channel(p->subs[SUB_REAL].owner)); zt_enable_ec(p); } @@ -3710,8 +3710,8 @@ static struct ast_frame *__zt_exception(struct ast_channel *ast) (res != ZT_EVENT_HOOKCOMPLETE)) { ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res); p->owner = p->subs[SUB_REAL].owner; - if (p->owner && p->owner->bridge) - ast_moh_stop(p->owner->bridge); + if (p->owner && ast_bridged_channel(p->owner)) + ast_moh_stop(ast_bridged_channel(p->owner)); } switch(res) { case ZT_EVENT_ONHOOK: @@ -3753,8 +3753,8 @@ static struct ast_frame *__zt_exception(struct ast_channel *ast) } p->callwaitingrepeat = 0; p->cidcwexpire = 0; - if (p->owner->bridge) - ast_moh_stop(p->owner->bridge); + if (ast_bridged_channel(p->owner)) + ast_moh_stop(ast_bridged_channel(p->owner)); } else ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); update_conf(p); @@ -5014,10 +5014,10 @@ static void *ss_thread(void *data) len = 0; } else if (p->transfer && !strcmp(exten, ast_parking_ext()) && p->subs[SUB_THREEWAY].owner && - p->subs[SUB_THREEWAY].owner->bridge) { + ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { /* This is a three way call, the main call being a real channel, and we're parking the first call. */ - ast_masq_park_call(p->subs[SUB_THREEWAY].owner->bridge, chan, 0, NULL); + ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); break; @@ -5058,7 +5058,7 @@ static void *ss_thread(void *data) p->subs[SUB_THREEWAY].owner; struct zt_pvt *pbridge = NULL; /* set up the private struct of the bridged one, if any */ - if (nbridge && nbridge->bridge) pbridge = nbridge->bridge->pvt->pvt; + if (nbridge && ast_bridged_channel(nbridge)) pbridge = ast_bridged_channel(nbridge)->pvt->pvt; if (nbridge && (!strcmp(nbridge->type,"Zap")) && ISTRUNK(pbridge)) { @@ -5073,8 +5073,8 @@ static void *ss_thread(void *data) swap_subs(p, SUB_REAL, SUB_THREEWAY); unalloc_sub(p, SUB_THREEWAY); p->owner = p->subs[SUB_REAL].owner; - if (p->subs[SUB_REAL].owner->bridge) - ast_moh_stop(p->subs[SUB_REAL].owner->bridge); + if (ast_bridged_channel(p->subs[SUB_REAL].owner)) + ast_moh_stop(ast_bridged_channel(p->subs[SUB_REAL].owner)); ast_hangup(chan); return NULL; } else { diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index a754129f6..a964ea93a 100755 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -93,8 +93,9 @@ struct ast_channel { /*! Whether or not the generator should be interrupted by write */ int writeinterrupt; - /*! Who are we bridged to, if we're bridged */ - struct ast_channel *bridge; + /*! Who are we bridged to, if we're bridged Do not access directly, + use ast_bridged_channel(chan) */ + struct ast_channel *_bridge; /*! Who did we call? */ struct ast_channel *dialed; /*! Who called us? */ @@ -815,6 +816,9 @@ int ast_transfer(struct ast_channel *chan, char *dest); int ast_do_masquerade(struct ast_channel *chan); +/* Find bridged channel */ +struct ast_channel *ast_bridged_channel(struct ast_channel *chan); + /* Misc. functions below */ /* Helper function for migrating select to poll */ diff --git a/include/asterisk/channel_pvt.h b/include/asterisk/channel_pvt.h index 97a48f902..4343f09e9 100755 --- a/include/asterisk/channel_pvt.h +++ b/include/asterisk/channel_pvt.h @@ -69,6 +69,8 @@ struct ast_channel_pvt { int (*transfer)(struct ast_channel *chan, char *newdest); /*! Write a frame, in standard format */ int (*write_video)(struct ast_channel *chan, struct ast_frame *frame); + /*! Find bridged channel */ + struct ast_channel * (*bridged_channel)(struct ast_channel *chan, struct ast_channel *bridge); }; //! Create a channel structure @@ -682,8 +682,8 @@ static int action_status(struct mansession *s, struct message *m) } } while(c) { - if (c->bridge) - snprintf(bridge, sizeof(bridge), "Link: %s\r\n", c->bridge->name); + if (c->_bridge) + snprintf(bridge, sizeof(bridge), "Link: %s\r\n", c->_bridge->name); else bridge[0] = '\0'; ast_mutex_lock(&s->lock); |