diff --git a/channels/chan_sip.c b/channels/chan_sip.c index b9e15ce142..676c12494c 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -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); } } diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h index dbd217652f..07bad8ed88 100644 --- a/include/asterisk/frame.h +++ b/include/asterisk/frame.h @@ -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 { diff --git a/main/channel.c b/main/channel.c index 1f9128fe38..319fa6a8c4 100644 --- a/main/channel.c +++ b/main/channel.c @@ -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; diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 34bf3eafbc..a0dbf72e42 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -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)) {