<p>Joshua Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/7275">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Kevin Harwell: Looks good to me, but someone else must approve
Richard Mudgett: Looks good to me, approved
Joshua Colp: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_rtp_asterisk.c: Fix rtp source address learning for broken clients<br><br>Some clients do not send rtp packets every ptime ms. This can lead to<br>situations in which the rtp source learning algorithm will never learn<br>the address of the client. This has been discovered on a Mac mini with<br>a pjsip based softphone after updating to Sierra: as soon as USB<br>headsets are involved, the softphone will send the second packet 30ms<br>after the first, the third 30ms after the second and the fourth 1ms<br>after the third. So in the old implmentation the rtp source learning<br>algorithm was repeatedly reset on the fourth packet.<br><br>The patch changes the algorithm in a way that doesn't take the arrival<br>time between two consecutive packets into account but the time between<br>the first and the last packet of a learning sequence.<br><br>The patch also fixes a second problem: when a user was using a wrong<br>value for the probation setting there was a LOG_WARNING output stating<br>that the value had been set to the default value instead. However<br>the code for setting the value back to defaults was missing.<br><br>ASTERISK-27421 #close<br><br>Change-Id: If778fe07678a6fd2041eaca7cd78267d0ef4fc6c<br>---<br>M res/res_rtp_asterisk.c<br>1 file changed, 35 insertions(+), 14 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c<br>index 15ca150..e28eb0a 100644<br>--- a/res/res_rtp_asterisk.c<br>+++ b/res/res_rtp_asterisk.c<br>@@ -113,6 +113,20 @@<br> #define ZFONE_PROFILE_ID 0x505a<br> <br> #define DEFAULT_LEARNING_MIN_SEQUENTIAL 4<br>+/*!<br>+ * \brief Calculate the min learning duration in ms.<br>+ *<br>+ * \details<br>+ * The min supported packet size represents 10 ms and we need to account<br>+ * for some jitter and fast clocks while learning. Some messed up devices<br>+ * have very bad jitter for a small packet sample size. Jitter can also<br>+ * be introduced by the network itself.<br>+ *<br>+ * So we'll allow packets to come in every 9ms on average for fast clocking<br>+ * with the last one coming in 5ms early for jitter.<br>+ */<br>+#define CALC_LEARNING_MIN_DURATION(count) (((count) - 1) * 9 - 5)<br>+#define DEFAULT_LEARNING_MIN_DURATION CALC_LEARNING_MIN_DURATION(DEFAULT_LEARNING_MIN_SEQUENTIAL)<br> <br> #define SRTP_MASTER_KEY_LEN 16<br> #define SRTP_MASTER_SALT_LEN 14<br>@@ -151,6 +165,7 @@<br> #endif<br> static int strictrtp = DEFAULT_STRICT_RTP; /*!< Only accept RTP frames from a defined source. If we receive an indication of a changing source, enter learning mode. */<br> static int learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL; /*!< Number of sequential RTP frames needed from a single source during learning mode to accept new source. */<br>+static int learning_min_duration = DEFAULT_LEARNING_MIN_DURATION; /*!< Lowest acceptable timeout between the first and the last sequential RTP frame. */<br> #ifdef HAVE_PJPROJECT<br> static int icesupport = DEFAULT_ICESUPPORT;<br> static struct sockaddr_in stunaddr;<br>@@ -231,7 +246,7 @@<br> struct rtp_learning_info {<br> struct ast_sockaddr proposed_address; /*!< Proposed remote address for strict RTP */<br> struct timeval start; /*!< The time learning mode was started */<br>- struct timeval received; /*!< The time of the last received packet */<br>+ struct timeval received; /*!< The time of the first received packet */<br> int max_seq; /*!< The highest sequence number received */<br> int packets; /*!< The number of remaining packets before the source is accepted */<br> };<br>@@ -3065,25 +3080,28 @@<br> */<br> static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t seq)<br> {<br>- /*<br>- * During the learning mode the minimum amount of media we'll accept is<br>- * 10ms so give a reasonable 5ms buffer just in case we get it sporadically.<br>- */<br>- if (!ast_tvzero(info->received) && ast_tvdiff_ms(ast_tvnow(), info->received) < 5) {<br>- /*<br>- * Reject a flood of packets as acceptable for learning.<br>- * Reset the needed packets.<br>- */<br>- info->packets = learning_min_sequential - 1;<br>- } else if (seq == (uint16_t) (info->max_seq + 1)) {<br>+ if (seq == (uint16_t) (info->max_seq + 1)) {<br> /* packet is in sequence */<br> info->packets--;<br> } else {<br> /* Sequence discontinuity; reset */<br> info->packets = learning_min_sequential - 1;<br>+ info->received = ast_tvnow();<br>+ }<br>+<br>+ /*<br>+ * Protect against packet floods by checking that we<br>+ * received the packet sequence in at least the minimum<br>+ * allowed time.<br>+ */<br>+ if (ast_tvzero(info->received)) {<br>+ info->received = ast_tvnow();<br>+ } else if (!info->packets && (ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration )) {<br>+ /* Packet flood; reset */<br>+ info->packets = learning_min_sequential - 1;<br>+ info->received = ast_tvnow();<br> }<br> info->max_seq = seq;<br>- info->received = ast_tvnow();<br> <br> return info->packets;<br> }<br>@@ -7140,6 +7158,7 @@<br> dtmftimeout = DEFAULT_DTMF_TIMEOUT;<br> strictrtp = DEFAULT_STRICT_RTP;<br> learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL;<br>+ learning_min_duration = DEFAULT_LEARNING_MIN_DURATION;<br> <br> /** This resource is not "reloaded" so much as unloaded and loaded again.<br> * In the case of the TURN related variables, the memory referenced by a<br>@@ -7204,10 +7223,12 @@<br> strictrtp = ast_true(s);<br> }<br> if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {<br>- if ((sscanf(s, "%d", &learning_min_sequential) <= 0) || learning_min_sequential <= 0) {<br>+ if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) {<br> ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",<br> DEFAULT_LEARNING_MIN_SEQUENTIAL);<br>+ learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL;<br> }<br>+ learning_min_duration = CALC_LEARNING_MIN_DURATION(learning_min_sequential);<br> }<br> #ifdef HAVE_PJPROJECT<br> if ((s = ast_variable_retrieve(cfg, "general", "icesupport"))) {<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7275">change 7275</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/7275"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 15 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: If778fe07678a6fd2041eaca7cd78267d0ef4fc6c </div>
<div style="display:none"> Gerrit-Change-Number: 7275 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Pirmin Walthert <infos@nappsoft.ch> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Richard Mudgett <rmudgett@digium.com> </div>