[asterisk-commits] jrose: trunk r367640 - in /trunk: channels/ include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 24 13:56:51 CDT 2012


Author: jrose
Date: Thu May 24 13:56:43 2012
New Revision: 367640

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=367640
Log:
chan_sip: fix problem directmediapermit/deny uses the wrong address

When remotely bridging calls with directmedia, Asterisk would check
the address of the peers/users holding directmedia ACLs (set via
directmediapermit/directmediadeny) instead of the bridged peer. This
is similar to r366547, but trunk specific and involves changes to
the rtpengine instead of just chan_sip.

(closes issue AST-876)
review: https://reviewboard.asterisk.org/r/1924/

Modified:
    trunk/channels/chan_sip.c
    trunk/include/asterisk/rtp_engine.h
    trunk/main/rtp_engine.c

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=367640&r1=367639&r2=367640
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Thu May 24 13:56:43 2012
@@ -30370,7 +30370,7 @@
 	return 0;
 }
 
-static int apply_directmedia_ha(struct sip_pvt *p, const char *op)
+static int apply_directmedia_ha(struct sip_pvt *p, struct ast_ha *directmediaha, const char *op)
 {
 	struct ast_sockaddr us = { { 0, }, }, them = { { 0, }, };
 	int res = AST_SENSE_ALLOW;
@@ -30378,7 +30378,7 @@
 	ast_rtp_instance_get_remote_address(p->rtp, &them);
 	ast_rtp_instance_get_local_address(p->rtp, &us);
 
-	if ((res = ast_apply_ha(p->directmediaha, &them)) == AST_SENSE_DENY) {
+	if ((res = ast_apply_ha(directmediaha, &them)) == AST_SENSE_DENY) {
 		const char *us_addr = ast_strdupa(ast_sockaddr_stringify(&us));
 		const char *them_addr = ast_strdupa(ast_sockaddr_stringify(&them));
 
@@ -30398,12 +30398,10 @@
 	if (!p) {
 		return NULL;
 	}
-	
+
 	sip_pvt_lock(p);
 	if (p->udptl && ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA)) {
-		if (apply_directmedia_ha(p, "UDPTL T.38 data")) {
-			udptl = p->udptl;
-		}
+		udptl = p->udptl;
 	}
 	sip_pvt_unlock(p);
 	return udptl;
@@ -30452,6 +30450,74 @@
 	return 0;
 }
 
+static int sip_allow_anyrtp_remote(struct ast_channel *chan1, struct ast_channel *chan2, char *rtptype)
+{
+	struct sip_pvt *p1 = NULL, *p2 = NULL;
+	struct ast_ha *p2_directmediaha = NULL; /* opposed directmediaha for comparing against first channel host address */
+	struct ast_ha *p1_directmediaha = NULL; /* opposed directmediaha for comparing against second channel host address */
+	int res = 1;
+
+	if (!(p1 = ast_channel_tech_pvt(chan1))) {
+		return 0;
+	}
+
+	if (!(p2 = ast_channel_tech_pvt(chan2))) {
+		return 0;
+	}
+
+	sip_pvt_lock(p2);
+	if (p2->relatedpeer->directmediaha) {
+		p2_directmediaha = ast_duplicate_ha_list(p2->relatedpeer->directmediaha);
+	}
+	sip_pvt_unlock(p2);
+
+	sip_pvt_lock(p1);
+	if (p1->relatedpeer->directmediaha) {
+		p1_directmediaha = ast_duplicate_ha_list(p1->relatedpeer->directmediaha);
+	}
+
+	if (ast_test_flag(&p1->flags[0], SIP_DIRECT_MEDIA)) {
+		if (!apply_directmedia_ha(p1, p2_directmediaha, rtptype)) {
+			res = 0;
+		}
+	}
+	sip_pvt_unlock(p1);
+
+	if (res == 0) {
+		goto allow_anyrtp_remote_end;
+	}
+
+	sip_pvt_lock(p2);
+	if (ast_test_flag(&p2->flags[0], SIP_DIRECT_MEDIA)) {
+		if (!apply_directmedia_ha(p2, p1_directmediaha, rtptype)) {
+			res = 0;
+		}
+	}
+	sip_pvt_unlock(p2);
+
+allow_anyrtp_remote_end:
+
+	if (p2_directmediaha) {
+		ast_free_ha(p2_directmediaha);
+	}
+
+	if (p1_directmediaha) {
+		ast_free_ha(p1_directmediaha);
+	}
+
+	return res;
+}
+
+static int sip_allow_rtp_remote(struct ast_channel *chan1, struct ast_channel *chan2)
+{
+	return sip_allow_anyrtp_remote(chan1, chan2, "audio");
+}
+
+static int sip_allow_vrtp_remote(struct ast_channel *chan1, struct ast_channel *chan2)
+{
+	return sip_allow_anyrtp_remote(chan1, chan2, "video");
+}
+
 static enum ast_rtp_glue_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
 {
 	struct sip_pvt *p = NULL;
@@ -30472,9 +30538,6 @@
 
 	if (ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA)) {
 		res = AST_RTP_GLUE_RESULT_REMOTE;
-		if (!apply_directmedia_ha(p, "audio")) {
-			res = AST_RTP_GLUE_RESULT_FORBID;
-		}
 	} else if (ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA_NAT)) {
 		res = AST_RTP_GLUE_RESULT_REMOTE;
 	} else if (ast_test_flag(&global_jbconf, AST_JB_FORCED)) {
@@ -30510,9 +30573,6 @@
 
 	if (ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA)) {
 		res = AST_RTP_GLUE_RESULT_REMOTE;
-		if (!apply_directmedia_ha(p, "video")) {
-			res = AST_RTP_GLUE_RESULT_FORBID;
-		}
 	}
 
 	sip_pvt_unlock(p);
@@ -30540,9 +30600,6 @@
 
 	if (ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA)) {
 		res = AST_RTP_GLUE_RESULT_REMOTE;
-		if (!apply_directmedia_ha(p, "text")) {
-			res = AST_RTP_GLUE_RESULT_FORBID;
-		}
 	}
 
 	sip_pvt_unlock(p);
@@ -30680,7 +30737,9 @@
 static struct ast_rtp_glue sip_rtp_glue = {
 	.type = "SIP",
 	.get_rtp_info = sip_get_rtp_peer,
+	.allow_rtp_remote = sip_allow_rtp_remote,
 	.get_vrtp_info = sip_get_vrtp_peer,
+	.allow_vrtp_remote = sip_allow_vrtp_remote,
 	.get_trtp_info = sip_get_trtp_peer,
 	.update_peer = sip_set_rtp_peer,
 	.get_codec = sip_get_codec,

Modified: trunk/include/asterisk/rtp_engine.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/rtp_engine.h?view=diff&rev=367640&r1=367639&r2=367640
==============================================================================
--- trunk/include/asterisk/rtp_engine.h (original)
+++ trunk/include/asterisk/rtp_engine.h Thu May 24 13:56:43 2012
@@ -405,10 +405,25 @@
 	 */
 	enum ast_rtp_glue_result (*get_rtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
 	/*!
+	 * \brief Used to prevent two channels from remotely bridging audio rtp if the channel tech has a
+	 *        reason for prohibiting it based on qualities that need to be compared from both channels.
+	 * \note This function should only be called with two channels of the same technology
+	 * \note This function may be NULL for a given channel driver. This should be accounted for and if that is the case, function this is not used.
+	 */
+	int (*allow_rtp_remote)(struct ast_channel *chan1, struct ast_channel *chan2);
+	/*!
 	 * \brief Callback for retrieving the RTP instance carrying video
 	 * \note This function increases the reference count on the returned RTP instance.
 	 */
 	enum ast_rtp_glue_result (*get_vrtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance);
+	/*!
+	 * \brief Used to prevent two channels from remotely bridging video rtp if the channel tech has a
+	 *        reason for prohibiting it based on qualities that need to be compared from both channels.
+	 * \note This function should only be called with two channels of the same technology
+	 * \note This function may be NULL for a given channel driver. This should be accounted for and if that is the case, this function is not used.
+	 */
+	int (*allow_vrtp_remote)(struct ast_channel *chan1, struct ast_channel *chan2);
+
 	/*!
 	 * \brief Callback for retrieving the RTP instance carrying text
 	 * \note This function increases the reference count on the returned RTP instance.

Modified: trunk/main/rtp_engine.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/rtp_engine.c?view=diff&rev=367640&r1=367639&r2=367640
==============================================================================
--- trunk/main/rtp_engine.c (original)
+++ trunk/main/rtp_engine.c Thu May 24 13:56:43 2012
@@ -1339,6 +1339,22 @@
 	audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
 	video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
 
+	/* If the channels are of the same technology, they might have limitations on remote bridging */
+	if (ast_channel_tech(c0) == ast_channel_tech(c1)) {
+		if (audio_glue0_res == audio_glue1_res && audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) {
+			if (glue0->allow_rtp_remote && !(glue0->allow_rtp_remote(c0, c1))) {
+				/* If the allow_rtp_remote indicates that remote isn't allowed, revert to local bridge */
+				audio_glue0_res = audio_glue1_res = AST_RTP_GLUE_RESULT_LOCAL;
+			}
+		}
+		if (video_glue0_res == video_glue1_res && video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) {
+			if (glue0->allow_vrtp_remote && !(glue0->allow_vrtp_remote(c0, c1))) {
+				/* if the allow_vrtp_remote indicates that remote isn't allowed, revert to local bridge */
+				video_glue0_res = video_glue1_res = AST_RTP_GLUE_RESULT_LOCAL;
+			}
+		}
+	}
+
 	/* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
 	if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
 		audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;




More information about the asterisk-commits mailing list