]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix bad RTP media bridges in directmedia calls on peers separated by multiple Asteris...
authorJonathan Rose <jrose@digium.com>
Fri, 16 Sep 2011 19:53:40 +0000 (19:53 +0000)
committerJonathan Rose <jrose@digium.com>
Fri, 16 Sep 2011 19:53:40 +0000 (19:53 +0000)
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/1.8@336294 65c4cc65-6c06-0410-ace0-fbb531ad65f3

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

index b9e15ce142cad552fcba4a224a0f5fd2c872e449..676c12494c0d762328e6d83f7e1aa753df305247 100644 (file)
@@ -19608,7 +19608,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
@@ -22437,6 +22437,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);
                                }
                        }
 
index dbd217652fa3230c990dd65323f788c96df84431..07bad8ed88e6f8dc1109ffa410a75a5d97f18aff 100644 (file)
@@ -335,6 +335,7 @@ enum ast_control_frame_type {
        AST_CONTROL_AOC = 28,                   /*!< Advice of Charge with encoded generic AOC payload */
        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_UPDATE_RTP_PEER = 31, /*!< Interrupt the bridge and have it update the peer */
 };
 
 enum ast_frame_read_action {
index 1f9128fe387b4cbe25ec585f96d1d40b0b735643..319fa6a8c4e8039cb30e5426f2ac5ddc165e457e 100644 (file)
@@ -4291,6 +4291,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
        case AST_CONTROL_READ_ACTION:
        case AST_CONTROL_AOC:
        case AST_CONTROL_END_OF_Q:
+       case AST_CONTROL_UPDATE_RTP_PEER:
                break;
 
        case AST_CONTROL_INCOMPLETE:
@@ -4478,6 +4479,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
        case AST_CONTROL_READ_ACTION:
        case AST_CONTROL_AOC:
        case AST_CONTROL_END_OF_Q:
+       case AST_CONTROL_UPDATE_RTP_PEER:
                /* Nothing left to do for these. */
                res = 0;
                break;
index 34bf3eafbc749ac6cf228735ccbb2c968c0e235a..a0dbf72e425d2e3dc6175fb4c1b57bcfb222f7fa 100644 (file)
@@ -1134,7 +1134,8 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct
                            (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) {
@@ -1142,8 +1143,10 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct
                                        } 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, codec0, 0);
                                        } else {
@@ -1162,7 +1165,10 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, struct
                                if (glue1->get_codec && c1->tech_pvt) {
                                        oldcodec1 = codec1 = glue1->get_codec(c1);
                                }
-                               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)) {