[asterisk-commits] jrose: trunk r351290 - in /trunk: ./ configs/ res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jan 17 11:15:10 CST 2012


Author: jrose
Date: Tue Jan 17 11:15:05 2012
New Revision: 351290

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=351290
Log:
Adds pjmedia probation concepts to res_rtp_asterisk's learning mode.

In order to better handle RTP sources with strictrtp enabled (which is now default in 10)
using the learning mode to figure out new sources when they change is handled by checking
for a number of consecutive (by sequence number) packets received to an rtp struct
based on a new configurable value called 'probation'. Also, during learning mode instead
of liberally accepting all packets received, we now reject packets until a clear source
has been determined.

Review: https://reviewboard.asterisk.org/r/1663/
........

Merged revisions 351287 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 351289 from http://svn.asterisk.org/svn/asterisk/branches/10

Modified:
    trunk/   (props changed)
    trunk/CHANGES
    trunk/configs/rtp.conf.sample
    trunk/res/res_rtp_asterisk.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-10-merged' - no diff available.

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=351290&r1=351289&r2=351290
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Tue Jan 17 11:15:05 2012
@@ -107,6 +107,17 @@
    connected line changes when they occur.  This is similar to app_dial
    and app_queue.
  * The 'N' option is now ignored if the call is already answered.
+
+RTP changes
+-------------
+ * A new option, 'probation' has been added to rtp.conf
+   RTP in strictrtp mode can now require more than 1 packet to exit learning
+   mode with a new source (and by default requires 4). The probation option
+   allows the user to change the required number of packets in sequence to any
+   desired value. Use a value of 1 to essentially restore the old behavior.
+   Also, with strictrtp on, Asterisk will now drop all packets until learning
+   mode has successfully exited. These changes are based on how pjmedia handles
+   media sources and source changes.
 
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 1.8 to Asterisk 10 -------------------

Modified: trunk/configs/rtp.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/rtp.conf.sample?view=diff&rev=351290&r1=351289&r2=351290
==============================================================================
--- trunk/configs/rtp.conf.sample (original)
+++ trunk/configs/rtp.conf.sample Tue Jan 17 11:15:05 2012
@@ -25,3 +25,10 @@
 ; do not come from the source of the RTP stream. This option is
 ; enabled by default.
 ; strictrtp=yes
+;
+; Number of packets containing consecutive sequence values needed
+; to change the RTP source socket address. This option only comes
+; into play while using strictrtp=yes. Consider changing this value
+; if rtp packets are dropped from one or both ends after a call is
+; connected. This option is set to 4 by default.
+; probation=8

Modified: trunk/res/res_rtp_asterisk.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_rtp_asterisk.c?view=diff&rev=351290&r1=351289&r2=351290
==============================================================================
--- trunk/res/res_rtp_asterisk.c (original)
+++ trunk/res/res_rtp_asterisk.c Tue Jan 17 11:15:05 2012
@@ -80,6 +80,8 @@
 
 #define ZFONE_PROFILE_ID 0x505a
 
+#define DEFAULT_LEARNING_MIN_SEQUENTIAL 4
+
 extern struct ast_srtp_res *res_srtp;
 static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
 
@@ -96,7 +98,8 @@
 #ifdef SO_NO_CHECK
 static int nochecksums;
 #endif
-static int strictrtp;
+static int strictrtp;			/*< Only accept RTP frames from a defined source. If we receive an indication of a changing source, enter learning mode. */
+static int learning_min_sequential;	/*< Number of sequential RTP frames needed from a single source during learning mode to accept new source. */
 
 enum strict_rtp_state {
 	STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
@@ -175,6 +178,13 @@
 	enum strict_rtp_state strict_rtp_state; /*!< Current state that strict RTP protection is in */
 	struct ast_sockaddr strict_rtp_address;  /*!< Remote address information for strict RTP purposes */
 	struct ast_sockaddr alt_rtp_address; /*!<Alternate remote address information */
+
+	/*
+	 * Learning mode values based on pjmedia's probation mode.  Many of these values are redundant to the above,
+	 * but these are in place to keep learning mode sequence values sealed from their normal counterparts.
+	 */
+	uint16_t learning_max_seq;		/*!< Highest sequence number heard */
+	int learning_probation;		/*!< Sequential packets untill source is valid */
 
 	struct rtp_red *red;
 };
@@ -460,6 +470,52 @@
 	return sock;
 }
 
+/*!
+ * \internal
+ * \brief Initializes sequence values and probation for learning mode.
+ * \note This is an adaptation of pjmedia's pjmedia_rtp_seq_init function.
+ *
+ * \param rtp pointer to rtp struct used with the received rtp packet.
+ * \param seq sequence number read from the rtp header
+ */
+static void rtp_learning_seq_init(struct ast_rtp *rtp, uint16_t seq)
+{
+	rtp->learning_max_seq = seq - 1;
+	rtp->learning_probation = learning_min_sequential;
+}
+
+/*!
+ * \internal
+ * \brief Updates sequence information for learning mode and determines if probation/learning mode should remain in effect.
+ * \note This function was adapted from pjmedia's pjmedia_rtp_seq_update function.
+ *
+ * \param rtp pointer to rtp struct used with the received rtp packet.
+ * \param seq sequence number read from the rtp header
+ * \return boolean value indicating if probation mode is active at the end of the function
+ */
+static int rtp_learning_rtp_seq_update(struct ast_rtp *rtp, uint16_t seq)
+{
+	int probation = 0;
+
+	ast_debug(1, "%p -- probation = %d, seq = %d\n", rtp, rtp->learning_probation, seq);
+
+	probation = 1;
+
+	if (seq == rtp->learning_max_seq + 1) {
+		/* packet is in sequence */
+		rtp->learning_probation--;
+		rtp->learning_max_seq = seq;
+		if (rtp->learning_probation == 0) {
+			probation = 0;
+		}
+	} else {
+		rtp->learning_probation = learning_min_sequential - 1;
+		rtp->learning_max_seq = seq;
+	}
+
+	return probation;
+}
+
 static int ast_rtp_new(struct ast_rtp_instance *instance,
 		       struct ast_sched_context *sched, struct ast_sockaddr *addr,
 		       void *data)
@@ -476,6 +532,9 @@
 	rtp->ssrc = ast_random();
 	rtp->seqno = ast_random() & 0xffff;
 	rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
+	if (strictrtp) {
+		rtp_learning_seq_init(rtp, (uint16_t)rtp->seqno);
+	}
 
 	/* Create a new socket for us to listen on and use */
 	if ((rtp->s =
@@ -2082,7 +2141,17 @@
 
 	/* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
 	if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
+		ast_debug(1, "%p -- start learning mode pass with addr = %s\n", rtp, ast_sockaddr_stringify(&addr));
+		/* For now, we always copy the address. */
 		ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
+
+		/* Send the rtp and the seqno from header to rtp_learning_rtp_seq_update to see whether we can exit or not*/
+		if (rtp_learning_rtp_seq_update(rtp, ntohl(rtpheader[0]))) {
+			ast_debug(1, "%p -- Condition for learning hasn't exited, so reject the frame.\n", rtp);
+			return &ast_null_frame;
+		}
+
+		ast_debug(1, "%p -- Probation Ended. Set strict_rtp_state to STRICT_RTP_CLOSED with address %s\n", rtp, ast_sockaddr_stringify(&addr));
 		rtp->strict_rtp_state = STRICT_RTP_CLOSED;
 	} else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
 		if (ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
@@ -2497,6 +2566,7 @@
 
 	if (strictrtp) {
 		rtp->strict_rtp_state = STRICT_RTP_LEARN;
+		rtp_learning_seq_init(rtp, rtp->seqno);
 	}
 
 	return;
@@ -2884,6 +2954,7 @@
 	rtpend = DEFAULT_RTP_END;
 	dtmftimeout = DEFAULT_DTMF_TIMEOUT;
 	strictrtp = STRICT_RTP_CLOSED;
+	learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL;
 	if (cfg) {
 		if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
 			rtpstart = atoi(s);
@@ -2927,6 +2998,12 @@
 		if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
 			strictrtp = ast_true(s);
 		}
+		if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
+			if ((sscanf(s, "%d", &learning_min_sequential) <= 0) || learning_min_sequential <= 0) {
+				ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
+					DEFAULT_LEARNING_MIN_SEQUENTIAL);
+			}
+		}
 		ast_config_destroy(cfg);
 	}
 	if (rtpstart >= rtpend) {




More information about the asterisk-commits mailing list