diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 460e30ece24d04d746356117c120725a6a619f5f..9134f4453cb5928a786ffdfc64a2b7b1d48a96c5 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -20141,7 +20141,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
@@ -23024,6 +23024,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);
 				}
 			}
 
@@ -29286,7 +29287,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;
 	}
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index f8cb71c6ace3432dcca9a641123afc919f83d92c..4e013534db735b55a70ddcb37f99402c6fd77f0e 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -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 {
diff --git a/main/channel.c b/main/channel.c
index 4015e80a1e12cdf39a09fbba21358dbb0b518890..2393b6a0405c3d5f5143f3a5b2e747030e2706f3 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -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;
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 9605d62775a68f38ea9fdcec85c9c8b2b85a9e15..730fdcdb2d1245caf43004ea43b9ff22512f6a46 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -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)) {