]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
prevent seg fault with attempt_transfer (bug #2741)
authorRussell Bryant <russell@russellbryant.com>
Tue, 2 Nov 2004 12:56:15 +0000 (12:56 +0000)
committerRussell Bryant <russell@russellbryant.com>
Tue, 2 Nov 2004 12:56:15 +0000 (12:56 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-0@4146 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
channels/chan_sip.c
res/res_features.c

diff --git a/CHANGES b/CHANGES
index 7e93804bb76d2b253635119ca680110493d80e53..d86699616818e92782727b2f7ced4936d01a40ed 100755 (executable)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,5 @@
- -- chan_h323
-    -- fix summaries for CLI commands 
+ -- chan_sip
+    -- fix to prevent seg fault when attempting a transfer
 Asterisk 1.0.2
  -- Major bugfix release
 Asterisk 1.0.1
index e6fa494503ce028def13c470cbfde2f5af2f2a94..ad3f471963dd8c41fe35f7eaafc091dd3c5b413e 100755 (executable)
@@ -7007,54 +7007,69 @@ static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct
        return -1;
 }
 
+static void ast_quiet_chan(struct ast_channel *chan) {
+       if(chan && chan->_state == AST_STATE_UP) {
+               if(chan->generatordata)
+               ast_deactivate_generator(chan);
+       }
+}
 
 /*--- attempt_transfer: Attempt transfer of SIP call ---*/
 static int attempt_transfer(struct sip_pvt *p1, struct sip_pvt *p2)
 {
+       int res = 0;
+       struct ast_channel
+               *chana = NULL,
+               *chanb = NULL,
+               *bridgea = NULL,
+               *bridgeb = NULL,
+               *peera = NULL,
+               *peerb = NULL,
+               *peerc = NULL;
+
        if (!p1->owner || !p2->owner) {
                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 (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_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);
-                       return -1;
-               }
-       } else if (p2->owner->bridge) {
-               ast_moh_stop(p2->owner->bridge);
-               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;
+       chana = p1->owner;
+       chanb = p2->owner;
+       bridgea = p1->owner->bridge;
+       bridgeb = p2->owner->bridge;
+
+       if (bridgea) {
+               peera = chana;
+               peerb = chanb;
+               peerc = bridgea;
+       } else if(bridgeb) {
+               peera = chanb;
+               peerb = chana;
+               peerc = bridgeb;
+       }
+
+       if(peera && peerb && peerc) {
+               ast_quiet_chan(peera);
+               ast_quiet_chan(peerb);
+               ast_quiet_chan(peerc);
+
+               if (peera->cdr && peerb->cdr) {
+                       peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
+               } else if(peera->cdr) {
+                       peerb->cdr = peera->cdr;
                }
-               if (p2->owner->bridge->cdr) {
-                       p1->owner->cdr = ast_cdr_append(p1->owner->cdr, p2->owner->bridge->cdr);
-                       p2->owner->bridge->cdr = NULL;
+               peera->cdr = NULL;
+
+               if (peerb->cdr && peerc->cdr) {
+                       peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
+               } else if(peerc->cdr) {
+                       peerb->cdr = peerc->cdr;
                }
-               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);
-                       return -1;
+               peerc->cdr = NULL;
+               if (ast_channel_masquerade(peerb, peerc)) {
+                       ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name);
+                       res = -1;
                }
+               return res;
        } else {
-               ast_log(LOG_NOTICE, "Transfer attempted with no bridged calls to transfer\n");
-               if (p1->owner)
-                       ast_softhangup_nolock(p1->owner, AST_SOFTHANGUP_DEV);
-               if (p2->owner)
-                       ast_softhangup_nolock(p2->owner, AST_SOFTHANGUP_DEV);
                return -1;
        }
        return 0;
index b2fd1a866d818c581b96691db643398792ec4d7f..409e04763898d437086151838dd54aa2fa375fe8 100755 (executable)
@@ -302,6 +302,12 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
        int allowdisconnect_in,allowdisconnect_out,allowredirect_in,allowredirect_out;
        char *monitor_exec;
 
+       if (chan && peer) {
+               pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
+               pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
+       } else if (chan)
+               pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
+
        if (monitor_ok) {
                if (!monitor_app) { 
                        if (!(monitor_app = pbx_findapp("Monitor")))
@@ -480,6 +486,8 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                                        }
                                        /* XXX Maybe we should have another message here instead of invalid extension XXX */
                                } else if (ast_exists_extension(transferee, transferer_real_context, newext, 1, transferer->callerid)) {
+                                       pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
+                                       pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
                                        ast_moh_stop(transferee);
                                        res=ast_autoservice_stop(transferee);
                                        if (!transferee->pbx) {