]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 336294 via svnmerge from
authorJonathan Rose <jrose@digium.com>
Fri, 16 Sep 2011 21:09:20 +0000 (21:09 +0000)
committerJonathan Rose <jrose@digium.com>
Fri, 16 Sep 2011 21:09:20 +0000 (21:09 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r336294 | jrose | 2011-09-16 14:53:40 -0500 (Fri, 16 Sep 2011) | 13 lines

  Fix bad RTP media bridges in directmedia calls on peers separated by multiple Asterisk nodes.

  In a situation involving devices on separate Asterisk trunks, the remote RTP bridge would
  break when starting a call with directmedia. This patch queues a new type of control frame
  so that our RTP bridge loop can properly detect when these situations occur and check to see
  if peers need to be updated in order to send their media to the proper location.

  (Closes issue ASTERISK-18340)
  Reported by: Thomas Arimont
  (Closes issue ASTERISK-17725)
  Reported by: kwk
  Tested by: twilson, jrose
........

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10@336307 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
include/asterisk/frame.h
main/channel.c
main/rtp_engine.c

index 7054efeb28933345ae5645ca907bed0904bce4e8..5a5dcd0005fce8b911ba03be74d8064ab5e55041 100644 (file)
@@ -20109,7 +20109,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
                                                "Channel: %s\r\nChanneltype: %s\r\nUniqueid: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n",
                                                p->owner->name, "SIP", p->owner->uniqueid, p->callid, p->fullcontact, p->peername);
                        } else {        /* RE-invite */
-                               ast_queue_frame(p->owner, &ast_null_frame);
+                               ast_queue_control(p->owner, AST_CONTROL_UPDATE_RTP_PEER);
                        }
                } else {
                         /* It's possible we're getting an 200 OK after we've tried to disconnect
@@ -22992,6 +22992,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                                } else {
                                        ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
                                        transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ?  XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE : TRUE, FALSE);
+                                       ast_queue_control(p->owner, AST_CONTROL_UPDATE_RTP_PEER);
                                }
                        }
 
@@ -29223,7 +29224,7 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
                memset(&p->tredirip, 0, sizeof(p->tredirip));
                changed = 1;
        }
-       if (cap && !(ast_format_cap_is_empty(cap) && !(ast_format_cap_identical(p->redircaps, cap)))) {
+       if (cap && !ast_format_cap_is_empty(cap) && !ast_format_cap_identical(p->redircaps, cap)) {
                ast_format_cap_copy(p->redircaps, cap);
                changed = 1;
        }
index f8cb71c6ace3432dcca9a641123afc919f83d92c..4e013534db735b55a70ddcb37f99402c6fd77f0e 100644 (file)
@@ -265,6 +265,7 @@ enum ast_control_frame_type {
        AST_CONTROL_END_OF_Q = 29,              /*!< Indicate that this position was the end of the channel queue for a softhangup. */
        AST_CONTROL_INCOMPLETE = 30,    /*!< Indication that the extension dialed is incomplete */
        AST_CONTROL_MCID = 31,                  /*!< Indicate that the caller is being malicious. */
+       AST_CONTROL_UPDATE_RTP_PEER = 32, /*!< Interrupt the bridge and have it update the peer */
 };
 
 enum ast_frame_read_action {
index 4015e80a1e12cdf39a09fbba21358dbb0b518890..2393b6a0405c3d5f5143f3a5b2e747030e2706f3 100644 (file)
@@ -4345,6 +4345,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
        case AST_CONTROL_AOC:
        case AST_CONTROL_END_OF_Q:
        case AST_CONTROL_MCID:
+       case AST_CONTROL_UPDATE_RTP_PEER:
                break;
 
        case AST_CONTROL_INCOMPLETE:
@@ -4533,6 +4534,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
        case AST_CONTROL_AOC:
        case AST_CONTROL_END_OF_Q:
        case AST_CONTROL_MCID:
+       case AST_CONTROL_UPDATE_RTP_PEER:
                /* Nothing left to do for these. */
                res = 0;
                break;
index 9605d62775a68f38ea9fdcec85c9c8b2b85a9e15..730fdcdb2d1245caf43004ea43b9ff22512f6a46 100644 (file)
@@ -1158,7 +1158,8 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
                            (fr->subclass.integer == AST_CONTROL_UNHOLD) ||
                            (fr->subclass.integer == AST_CONTROL_VIDUPDATE) ||
                            (fr->subclass.integer == AST_CONTROL_SRCUPDATE) ||
-                           (fr->subclass.integer == AST_CONTROL_T38_PARAMETERS)) {
+                           (fr->subclass.integer == AST_CONTROL_T38_PARAMETERS) ||
+                               (fr->subclass.integer == AST_CONTROL_UPDATE_RTP_PEER)) {
                                if (fr->subclass.integer == AST_CONTROL_HOLD) {
                                        /* If we someone went on hold we want the other side to reinvite back to us */
                                        if (who == c0) {
@@ -1166,8 +1167,10 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
                                        } else {
                                                glue0->update_peer(c0, NULL, NULL, NULL, 0, 0);
                                        }
-                               } else if (fr->subclass.integer == AST_CONTROL_UNHOLD) {
-                                       /* If they went off hold they should go back to being direct */
+                               } else if (fr->subclass.integer == AST_CONTROL_UNHOLD ||
+                                       fr->subclass.integer == AST_CONTROL_UPDATE_RTP_PEER) {
+                                       /* If they went off hold they should go back to being direct, or if we have
+                                        * been told to force a peer update, go ahead and do it. */
                                        if (who == c0) {
                                                glue1->update_peer(c1, instance0, vinstance0, tinstance0, cap0, 0);
                                        } else {
@@ -1193,7 +1196,10 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
                                        glue0->get_codec(c1, cap1);
                                        ast_format_cap_append(oldcap1, cap1);
                                }
-                               ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
+                               /* Since UPDATE_BRIDGE_PEER is only used by the bridging code, don't forward it */
+                               if (fr->subclass.integer != AST_CONTROL_UPDATE_RTP_PEER) {
+                                       ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
+                               }
                                ast_frfree(fr);
                        } else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
                                if (ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {