First pass at making transfer work within agent (not tested, shouldn't break anything...
authorMark Spencer <markster@digium.com>
Sat, 23 Oct 2004 12:19:47 +0000 (12:19 +0000)
committerMark Spencer <markster@digium.com>
Sat, 23 Oct 2004 12:19:47 +0000 (12:19 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4061 65c4cc65-6c06-0410-ace0-fbb531ad65f3

12 files changed:
channel.c
channels/chan_agent.c
channels/chan_iax2.c
channels/chan_local.c
channels/chan_mgcp.c
channels/chan_oss.c
channels/chan_sip.c
channels/chan_skinny.c
channels/chan_zap.c
include/asterisk/channel.h
include/asterisk/channel_pvt.h
manager.c

index 748ecaf..8d70ee2 100755 (executable)
--- a/channel.c
+++ b/channel.c
@@ -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"
index 2246bf9..706f675 100755 (executable)
@@ -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);
                                }
index 3e995e8..d8b0b38 100755 (executable)
@@ -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
index 9d004b5..fa879d5 100755 (executable)
@@ -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));
                }
        }
 }
index fd4aff6..4db202e 100755 (executable)
@@ -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);
index 61dd4ce..c1d5ee0 100755 (executable)
@@ -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");
index 1531dd0..56acb16 100755 (executable)
@@ -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);
index 3a37ea2..a77c4b1 100755 (executable)
@@ -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);
             }
index 0855ab6..ad9ba47 100755 (executable)
@@ -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 {
index a754129..a964ea9 100755 (executable)
@@ -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 */
index 97a48f9..4343f09 100755 (executable)
@@ -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
index 29f46c8..a1935ed 100755 (executable)
--- a/manager.c
+++ b/manager.c
@@ -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);