rtp_engine: Allow more than 32 dynamic payload types.
authorAlexander Traud <pabstraud@compuserve.com>
Tue, 13 Sep 2016 09:08:34 +0000 (11:08 +0200)
committerGeorge Joseph <gjoseph@digium.com>
Wed, 2 Nov 2016 13:44:26 +0000 (08:44 -0500)
Since adding all remaining rates of Signed Linear (ASTERISK-24274), SILK
(Gerrit 3136) and Codec 2 (ASTERISK-26217), no RTP Payload Type is left in the
dynamic range (96-127). RFC 3551 section 3 allows to reassign other ranges.
Consequently, when the dynamic range is exhausted, this change utilizes payload
types in the range between 35 and 63 giving room for another 29 payload types.

ASTERISK-26311 #close

Change-Id: I7bc96ab764bc30098a178b841cbf7146f9d64964

CHANGES
configs/samples/asterisk.conf.sample
include/asterisk/options.h
include/asterisk/rtp_engine.h
main/asterisk.c
main/rtp_engine.c

diff --git a/CHANGES b/CHANGES
index f4c5148..2131fee 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -49,6 +49,15 @@ cel_radius
  * To fix a memory leak the syslog channel is now empty if it has not been set
    and used by a syslog channel in the logger.
 
+RTP
+------------------
+ * New setting "rtp_pt_dynamic = 35" in asterisk.conf:
+   Normally the Dynamic RTP Payload Type numbers are 96-127, which allow just 32
+   formats. To avoid the message "No Dynamic RTP mapping available", the range
+   was changed to 35-63,96-127. This is allowed by RFC 3551 section 3. However,
+   when you use more than 32 formats and calls are not accepted by a remote
+   implementation, please report this and go back to rtp_pt_dynamic = 96.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ----------
 ------------------------------------------------------------------------------
index 6d6d2f0..e13a944 100644 (file)
@@ -97,6 +97,14 @@ documentation_language = en_US       ; Set the language you want documentation
                                ; This is currently is used by DUNDi and
                                ; Exchanging Device and Mailbox State
                                ; using protocols: XMPP, Corosync and PJSIP.
+;rtp_pt_dynamic = 35           ; Normally the Dynamic RTP Payload Type numbers
+                               ; are 96-127, which allow just 32 formats. The
+                               ; starting point 35 enables the range 35-63 and
+                               ; allows 29 additional formats. When you use
+                               ; more than 32 formats in the dynamic range and
+                               ; calls are not accepted by a remote
+                               ; implementation, please report this and go
+                               ; back to value 96.
 
 ; Changing the following lines may compromise your security.
 ;[files]
index e2709f9..345bacf 100644 (file)
@@ -155,6 +155,8 @@ extern int dahdi_chan_name_len;
 
 extern int ast_language_is_prefix;
 
+extern unsigned int ast_option_rtpptdynamic;
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
index a40472e..017bb7b 100644 (file)
@@ -84,6 +84,9 @@ extern "C" {
 /*! First dynamic RTP payload type */
 #define AST_RTP_PT_FIRST_DYNAMIC 96
 
+/*! Last reassignable RTP payload type */
+#define AST_RTP_PT_LAST_REASSIGN 63
+
 /*! Maximum number of generations */
 #define AST_RED_MAX_GENERATION 5
 
index 56fc107..be6c7cc 100644 (file)
@@ -248,6 +248,7 @@ int daemon(int, int);  /* defined in libresolv of all places */
 #include "asterisk/format_cache.h"
 #include "asterisk/media_cache.h"
 #include "asterisk/astdb.h"
+#include "asterisk/options.h"
 
 #include "../defaults.h"
 
@@ -336,6 +337,7 @@ unsigned int option_dtmfminduration;                /*!< Minimum duration of DTMF. */
 #if defined(HAVE_SYSINFO)
 long option_minmemfree;                                /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
 #endif
+unsigned int ast_option_rtpptdynamic;
 
 /*! @} */
 
@@ -599,6 +601,19 @@ static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_c
        ast_cli(a->fd, "  Generic PLC:                 %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
        ast_cli(a->fd, "  Min DTMF duration::          %u\n", option_dtmfminduration);
 
+       if (ast_option_rtpptdynamic == AST_RTP_PT_LAST_REASSIGN) {
+               ast_cli(a->fd, "  RTP dynamic payload types:   %u,%u-%u\n",
+                       ast_option_rtpptdynamic,
+                       AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
+       } else if (ast_option_rtpptdynamic < AST_RTP_PT_LAST_REASSIGN) {
+               ast_cli(a->fd, "  RTP dynamic payload types:   %u-%u,%u-%u\n",
+                       ast_option_rtpptdynamic, AST_RTP_PT_LAST_REASSIGN,
+                       AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
+       } else {
+               ast_cli(a->fd, "  RTP dynamic payload types:   %u-%u\n",
+                       AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
+       }
+
        ast_cli(a->fd, "\n* Subsystems\n");
        ast_cli(a->fd, "  -------------\n");
        ast_cli(a->fd, "  Manager (AMI):               %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
@@ -3464,6 +3479,7 @@ static void ast_readconfig(void)
 
        /* Set default value */
        option_dtmfminduration = AST_MIN_DTMF_DURATION;
+       ast_option_rtpptdynamic = 35;
 
        /* init with buildtime config */
        ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
@@ -3619,6 +3635,11 @@ static void ast_readconfig(void)
                        if (sscanf(v->value, "%30u", &option_dtmfminduration) != 1) {
                                option_dtmfminduration = AST_MIN_DTMF_DURATION;
                        }
+               /* http://www.iana.org/assignments/rtp-parameters
+                * RTP dynamic payload types start at 96 normally; extend down to 0 */
+               } else if (!strcasecmp(v->name, "rtp_pt_dynamic")) {
+                       ast_parse_arg(v->value, PARSE_UINT32|PARSE_IN_RANGE,
+                                     &ast_option_rtpptdynamic, 0, AST_RTP_PT_FIRST_DYNAMIC);
                } else if (!strcasecmp(v->name, "maxcalls")) {
                        if ((sscanf(v->value, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
                                ast_option_maxcalls = 0;
index c9d228c..4fc1414 100644 (file)
 
 #include "asterisk.h"
 
-#include <math.h>
-
-#include "asterisk/channel.h"
-#include "asterisk/frame.h"
-#include "asterisk/module.h"
-#include "asterisk/rtp_engine.h"
+#include <math.h>                       /* for sqrt, MAX */
+#include <sched.h>                      /* for sched_yield */
+#include <sys/time.h>                   /* for timeval */
+#include <time.h>                       /* for time_t */
+
+#include "asterisk/_private.h"          /* for ast_rtp_engine_init prototype */
+#include "asterisk/astobj2.h"           /* for ao2_cleanup, ao2_ref, etc */
+#include "asterisk/channel.h"           /* for ast_channel_name, etc */
+#include "asterisk/codec.h"             /* for ast_codec_media_type2str, etc */
+#include "asterisk/format.h"            /* for ast_format_cmp, etc */
+#include "asterisk/format_cache.h"      /* for ast_format_adpcm, etc */
+#include "asterisk/format_cap.h"        /* for ast_format_cap_alloc, etc */
+#include "asterisk/json.h"              /* for ast_json_ref, etc */
+#include "asterisk/linkedlists.h"       /* for ast_rtp_engine::<anonymous>, etc */
+#include "asterisk/lock.h"              /* for ast_rwlock_unlock, etc */
+#include "asterisk/logger.h"            /* for ast_log, ast_debug, etc */
 #include "asterisk/manager.h"
-#include "asterisk/options.h"
-#include "asterisk/astobj2.h"
-#include "asterisk/pbx.h"
-#include "asterisk/translate.h"
-#include "asterisk/netsock2.h"
-#include "asterisk/_private.h"
-#include "asterisk/framehook.h"
-#include "asterisk/stasis.h"
-#include "asterisk/json.h"
-#include "asterisk/stasis_channels.h"
+#include "asterisk/module.h"            /* for ast_module_unref, etc */
+#include "asterisk/netsock2.h"          /* for ast_sockaddr_copy, etc */
+#include "asterisk/options.h"           /* for ast_option_rtpptdynamic */
+#include "asterisk/pbx.h"               /* for pbx_builtin_setvar_helper */
+#include "asterisk/res_srtp.h"          /* for ast_srtp_res */
+#include "asterisk/rtp_engine.h"        /* for ast_rtp_codecs, etc */
+#include "asterisk/stasis.h"            /* for stasis_message_data, etc */
+#include "asterisk/stasis_channels.h"   /* for ast_channel_stage_snapshot, etc */
+#include "asterisk/strings.h"           /* for ast_str_append, etc */
+#include "asterisk/time.h"              /* for ast_tvdiff_ms, ast_tvnow */
+#include "asterisk/translate.h"         /* for ast_translate_available_formats */
+#include "asterisk/utils.h"             /* for ast_free, ast_strdup, etc */
+#include "asterisk/vector.h"            /* for AST_VECTOR_GET, etc */
 
 struct ast_srtp_res *res_srtp = NULL;
 struct ast_srtp_policy_res *res_srtp_policy = NULL;
@@ -2301,6 +2314,48 @@ static void add_static_payload(int map, struct ast_format *format, int rtp_code)
                        }
                }
 
+               /* http://www.iana.org/assignments/rtp-parameters
+                * RFC 3551, Section 3: "[...] applications which need to define more
+                * than 32 dynamic payload types MAY bind codes below 96, in which case
+                * it is RECOMMENDED that unassigned payload type numbers be used
+                * first". Updated by RFC 5761, Section 4: "[...] values in the range
+                * 64-95 MUST NOT be used [to avoid conflicts with RTCP]". Summaries:
+                * https://tools.ietf.org/html/draft-roach-mmusic-unified-plan#section-3.2.1.2
+                * https://tools.ietf.org/html/draft-wu-avtcore-dynamic-pt-usage#section-3
+                */
+               if (map < 0) {
+                       for (x = MAX(ast_option_rtpptdynamic, 35); x <= AST_RTP_PT_LAST_REASSIGN; ++x) {
+                               if (!static_RTP_PT[x]) {
+                                       map = x;
+                                       break;
+                               }
+                       }
+               }
+               /* Yet, reusing mappings below 35 is not supported in Asterisk because
+                * when Compact Headers are activated, no rtpmap is send for those below
+                * 35. If you want to use 35 and below
+                * A) do not use Compact Headers,
+                * B) remove that code in chan_sip/res_pjsip, or
+                * C) add a flag that this RTP Payload Type got reassigned dynamically
+                *    and requires a rtpmap even with Compact Headers enabled.
+                */
+               if (map < 0) {
+                       for (x = MAX(ast_option_rtpptdynamic, 20); x < 35; ++x) {
+                               if (!static_RTP_PT[x]) {
+                                       map = x;
+                                       break;
+                               }
+                       }
+               }
+               if (map < 0) {
+                       for (x = MAX(ast_option_rtpptdynamic, 0); x < 20; ++x) {
+                               if (!static_RTP_PT[x]) {
+                                       map = x;
+                                       break;
+                               }
+                       }
+               }
+
                if (map < 0) {
                        if (format) {
                                ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n",