<p>Bharat Ramaswamy-Nandakumar has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/13451">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Added RTT Support for PJSIP<br><br>Changes are:<br>1. chan_pjsip - added write_text function to the pjsip_tech driver<br>Added case for AST_FRAME_TEXT in chan_pjsip_write_stream<br>Added case to handle text in chan_pjsip_write<br><br>2. pjsip/dialplan_functions.c: added logic to handle media for TEXT<br><br>3.  res_pjsip.h: added variables to deal with endpoint media<br><br>4. channel.c: added  logic to add a stream_num for a frame<br><br>5.  frame.c: added code to handle and fix issues with red.<br><br>6. res_pjsip_sdp_rtp.c: added logic to setup SDP.<br>Added logic to handle tos and cos text<br>Added logic to RED for red enabled<br><br>7. res_pjsip_session.c: aded logic for max_text_streams<br><br>8. res_rtp_asterisk.c: Added logic to hanle Red and dealing with<br>a repeating RTP issue<br><br>9. pjsip_configuration.c: Added logic to handle text for PJSIP library<br><br>Issue ID: ASTERISK-28654<br><br>Reported-by: Bharat Ramaswamy Nandakumar(bharatram1)<br><br>Fixed by: Bharat Ramaswamy Nandakumar(bharatram1),<br>Seth Marks and Corey Wysong<br><br>Change-Id: I6b2ad94a065680ae9c4c933d338989e4b8c3a505<br>---<br>M channels/chan_pjsip.c<br>M channels/pjsip/dialplan_functions.c<br>M include/asterisk/res_pjsip.h<br>M main/channel.c<br>M main/frame.c<br>M res/res_pjsip/pjsip_configuration.c<br>M res/res_pjsip_sdp_rtp.c<br>M res/res_pjsip_session.c<br>M res/res_rtp_asterisk.c<br>9 files changed, 112 insertions(+), 8 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/51/13451/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c</span><br><span>index 8ce5630..6176b5c 100644</span><br><span>--- a/channels/chan_pjsip.c</span><br><span>+++ b/channels/chan_pjsip.c</span><br><span>@@ -121,6 +121,7 @@</span><br><span>        .read_stream = chan_pjsip_read_stream,</span><br><span>       .write = chan_pjsip_write,</span><br><span>   .write_stream = chan_pjsip_write_stream,</span><br><span style="color: hsl(120, 100%, 40%);">+      .write_text = chan_pjsip_write,</span><br><span>      .exception = chan_pjsip_read_stream,</span><br><span>         .indicate = chan_pjsip_indicate,</span><br><span>     .transfer = chan_pjsip_transfer,</span><br><span>@@ -986,6 +987,19 @@</span><br><span>              break;</span><br><span>       case AST_FRAME_CNG:</span><br><span>          break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case AST_FRAME_TEXT:</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!media) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             } else if (media->type != AST_MEDIA_TYPE_TEXT) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   ast_debug(3, "Channel %s stream %d is of type '%s', not text!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_channel_name(ast), stream_num, ast_codec_media_type2str(media->type));</span><br><span style="color: hsl(120, 100%, 40%);">+                 return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if(session->endpoint->media.red_enabled) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_rtp_red_buffer(media->rtp, frame);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if (media->write_callback) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     res = media->write_callback(session, media, frame);</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span>       case AST_FRAME_RTCP:</span><br><span>                 /* We only support writing out feedback */</span><br><span>           if (frame->subclass.integer != AST_RTP_RTCP_PSFB || !media) {</span><br><span>@@ -1008,6 +1022,10 @@</span><br><span> </span><br><span> static int chan_pjsip_write(struct ast_channel *ast, struct ast_frame *frame)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (frame->frametype == AST_FRAME_TEXT && frame->stream_num != -1){</span><br><span style="color: hsl(120, 100%, 40%);">+             return chan_pjsip_write_stream(ast, frame->stream_num, frame);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  return chan_pjsip_write_stream(ast, -1, frame);</span><br><span> }</span><br><span> </span><br><span>diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c</span><br><span>index 7cc4506..21296ed 100644</span><br><span>--- a/channels/pjsip/dialplan_functions.c</span><br><span>+++ b/channels/pjsip/dialplan_functions.c</span><br><span>@@ -576,7 +576,9 @@</span><br><span>              media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];</span><br><span>    } else if (!strcmp(field, "video")) {</span><br><span>              media = session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO];</span><br><span style="color: hsl(0, 100%, 40%);">-       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      } else if (ast_strlen_zero(field) || !strcmp(field, "text")){</span><br><span style="color: hsl(120, 100%, 40%);">+        media = session->active_media_state->default_session[AST_MEDIA_TYPE_TEXT];</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span>              ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtp' information\n", field);</span><br><span>          return -1;</span><br><span>   }</span><br><span>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h</span><br><span>index a78311d..e49dfe6 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -705,6 +705,12 @@</span><br><span>        unsigned int tos_video;</span><br><span>      /*! Priority for video streams */</span><br><span>    unsigned int cos_video;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! DSCP TOS bits for text streams */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int tos_text;</span><br><span style="color: hsl(120, 100%, 40%);">+        /*! Priority for text streams */</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned int cos_text;</span><br><span style="color: hsl(120, 100%, 40%);">+    /*! DSCP indicate if text stream supports RED */</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int red_enabled;       </span><br><span>     /*! Is g.726 packed in a non standard way */</span><br><span>         unsigned int g726_non_standard;</span><br><span>      /*! Bind the RTP instance to the media_address */</span><br><span>@@ -715,6 +721,8 @@</span><br><span>      unsigned int max_audio_streams;</span><br><span>      /*! Maximum number of video streams to offer/accept */</span><br><span>       unsigned int max_video_streams;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! Maximum number of text streams to offer/accept */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int max_text_streams;</span><br><span>       /*! Use BUNDLE */</span><br><span>    unsigned int bundle;</span><br><span>         /*! Enable webrtc settings and defaults */</span><br><span>diff --git a/main/channel.c b/main/channel.c</span><br><span>index c0a007e..09c222b 100644</span><br><span>--- a/main/channel.c</span><br><span>+++ b/main/channel.c</span><br><span>@@ -4698,6 +4698,7 @@</span><br><span>              f.frametype = AST_FRAME_TEXT;</span><br><span>                f.datalen = body_len;</span><br><span>                f.mallocd = AST_MALLOCD_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+         f.stream_num = ast_stream_get_position(ast_channel_get_default_stream(chan, AST_MEDIA_TYPE_TEXT));</span><br><span>           f.data.ptr = ast_strdup(body);</span><br><span>               if (f.data.ptr) {</span><br><span>                    res = ast_channel_tech(chan)->write_text(chan, &f);</span><br><span>diff --git a/main/frame.c b/main/frame.c</span><br><span>index 208c82d..6d76244 100644</span><br><span>--- a/main/frame.c</span><br><span>+++ b/main/frame.c</span><br><span>@@ -302,7 +302,7 @@</span><br><span> #endif</span><br><span> </span><br><span>  /* Start with standard stuff */</span><br><span style="color: hsl(0, 100%, 40%);">- len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;</span><br><span style="color: hsl(120, 100%, 40%);">+     len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen + 1;</span><br><span>        /* If we have a source, add space for it */</span><br><span>  /*</span><br><span>    * XXX Watch out here - if we receive a src which is not terminated</span><br><span>@@ -360,13 +360,16 @@</span><br><span>  if (out->datalen || f->frametype == AST_FRAME_TEXT) {</span><br><span>          out->data.ptr = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;</span><br><span>                 memcpy(out->data.ptr, f->data.ptr, out->datalen);</span><br><span style="color: hsl(120, 100%, 40%);">+            if(f->frametype == AST_FRAME_TEXT) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       ((char*)out->data.ptr)[out->datalen] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span>    } else {</span><br><span>             out->data.uint32 = f->data.uint32;</span><br><span>     }</span><br><span>    if (srclen > 0) {</span><br><span>                 /* This may seem a little strange, but it's to avoid a gcc (4.2.4) compiler warning */</span><br><span>           char *src;</span><br><span style="color: hsl(0, 100%, 40%);">-              out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;</span><br><span style="color: hsl(120, 100%, 40%);">+               out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen + 1;</span><br><span>          src = (char *) out->src;</span><br><span>          /* Must have space since we allocated for it */</span><br><span>              strcpy(src, f->src);</span><br><span>diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c</span><br><span>index e6937fb..22ca7aa 100644</span><br><span>--- a/res/res_pjsip/pjsip_configuration.c</span><br><span>+++ b/res/res_pjsip/pjsip_configuration.c</span><br><span>@@ -960,6 +960,8 @@</span><br><span>               endpoint->media.tos_audio = value;</span><br><span>        } else if (!strcmp(var->name, "tos_video")) {</span><br><span>           endpoint->media.tos_video = value;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcmp(var->name, "tos_text")){</span><br><span style="color: hsl(120, 100%, 40%);">+              endpoint->media.tos_text = value;</span><br><span>         } else {</span><br><span>             /* If we reach this point, someone called the tos_handler when they shouldn't have. */</span><br><span>           ast_assert(0);</span><br><span>@@ -988,6 +990,16 @@</span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int tos_text_to_str(const void *obj, const intptr_t *args, char **buf)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  const struct ast_sip_endpoint *endpoint = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (ast_asprintf(buf, "%u", endpoint->media.tos_text) == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int from_user_handler(const struct aco_option *opt,</span><br><span>         struct ast_variable *var, void *obj)</span><br><span> {</span><br><span>@@ -1904,8 +1916,10 @@</span><br><span>   ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_session", "Asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpsession));</span><br><span>     ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_audio", "0", tos_handler, tos_audio_to_str, NULL, 0, 0);</span><br><span>        ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_video", "0", tos_handler, tos_video_to_str, NULL, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_text", "0", tos_handler, tos_text_to_str, NULL, 0, 0);</span><br><span>  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_audio", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_audio));</span><br><span>         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_video", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_video));</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_text", "5", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_text));      </span><br><span>     ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_subscribe", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.allow));</span><br><span>      ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sub_min_expiry", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, subscription.minexpiry));</span><br><span>     ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "from_user", "", from_user_handler, from_user_to_str, NULL, 0, 0);</span><br><span>@@ -1945,6 +1959,7 @@</span><br><span>   ast_sorcery_object_field_register(sip_sorcery, "endpoint", "notify_early_inuse_ringing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, notify_early_inuse_ringing));</span><br><span>    ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_audio_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_audio_streams));</span><br><span>         ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_video_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_video_streams));</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_text_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_text_streams));      </span><br><span>     ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bundle", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.bundle));</span><br><span>      ast_sorcery_object_field_register(sip_sorcery, "endpoint", "webrtc", "no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, media.webrtc));</span><br><span>     ast_sorcery_object_field_register(sip_sorcery, "endpoint", "incoming_mwi_mailbox", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, incoming_mwi_mailbox));</span><br><span>diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c</span><br><span>index 8d9cece..770b1c3 100644</span><br><span>--- a/res/res_pjsip_sdp_rtp.c</span><br><span>+++ b/res/res_pjsip_sdp_rtp.c</span><br><span>@@ -65,6 +65,7 @@</span><br><span> </span><br><span> static const char STR_AUDIO[] = "audio";</span><br><span> static const char STR_VIDEO[] = "video";</span><br><span style="color: hsl(120, 100%, 40%);">+static const char STR_TEXT[] = "text";</span><br><span> </span><br><span> static int send_keepalive(const void *data)</span><br><span> {</span><br><span>@@ -268,7 +269,12 @@</span><br><span>                  (session->endpoint->media.tos_audio || session->endpoint->media.cos_audio)) {</span><br><span>            ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_audio,</span><br><span>                            session->endpoint->media.cos_audio, "SIP RTP Audio");</span><br><span style="color: hsl(0, 100%, 40%);">-   } else if (session_media->type == AST_MEDIA_TYPE_VIDEO) {</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (session_media->type == AST_MEDIA_TYPE_TEXT) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (session->endpoint->media.tos_text || session->endpoint->media.cos_text) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_text,</span><br><span style="color: hsl(120, 100%, 40%);">+                              session->endpoint->media.cos_text, "SIP RTP Text");</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (session_media->type == AST_MEDIA_TYPE_VIDEO) {</span><br><span>          ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RETRANS_RECV, session->endpoint->media.webrtc);</span><br><span>              ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RETRANS_SEND, session->endpoint->media.webrtc);</span><br><span>              ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_REMB, session->endpoint->media.webrtc);</span><br><span>@@ -340,7 +346,33 @@</span><br><span>                               struct ast_format *format_parsed;</span><br><span> </span><br><span>                                ast_copy_pj_str(fmt_param, &fmtp.fmt_param, sizeof(fmt_param));</span><br><span style="color: hsl(120, 100%, 40%);">+                           if(strncasecmp(name, "RED", 3) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                                        {</span><br><span style="color: hsl(120, 100%, 40%);">+                                             int red_data_pt[10];            /* For T.140 RED */</span><br><span style="color: hsl(120, 100%, 40%);">+                                           char red_cp_data[30];</span><br><span style="color: hsl(120, 100%, 40%);">+                                         char *red_cp = red_cp_data;</span><br><span style="color: hsl(120, 100%, 40%);">+                                           char *rest = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                                            int red_num_gen = -1;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+                                             strcpy(red_cp,fmt_param);</span><br><span style="color: hsl(120, 100%, 40%);">+                                             red_cp = strtok_r(red_cp, "/", &rest);</span><br><span style="color: hsl(120, 100%, 40%);">+                                          while (red_cp && (red_num_gen)++ < AST_RED_MAX_GENERATION) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       sscanf(red_cp, "%30u", (unsigned *)&red_data_pt[red_num_gen]);</span><br><span style="color: hsl(120, 100%, 40%);">+                                                  red_cp = strtok_r(NULL, "/", &rest);</span><br><span style="color: hsl(120, 100%, 40%);">+                                            }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                                           if(red_num_gen > 0){</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       session->endpoint->media.red_enabled=1;</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 ast_rtp_red_init(session_media->rtp, 300, red_data_pt, red_num_gen);</span><br><span style="color: hsl(120, 100%, 40%);">+                                               }</span><br><span style="color: hsl(120, 100%, 40%);">+                                             else{</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 session->endpoint->media.red_enabled=0;</span><br><span style="color: hsl(120, 100%, 40%);">+                                         }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                                   }</span><br><span style="color: hsl(120, 100%, 40%);">+                                     else{</span><br><span style="color: hsl(120, 100%, 40%);">+                                         session->endpoint->media.red_enabled=0;</span><br><span style="color: hsl(120, 100%, 40%);">+                                 }</span><br><span>                            format_parsed = ast_format_parse_sdp_fmtp(format, fmt_param);</span><br><span>                                if (format_parsed) {</span><br><span>                                         ast_rtp_codecs_payload_replace_format(codecs, num, format_parsed);</span><br><span>@@ -2109,6 +2141,17 @@</span><br><span>  .stream_destroy = stream_destroy,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief SDP handler for 'text' media stream */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_sip_session_sdp_handler text_sdp_handler = {</span><br><span style="color: hsl(120, 100%, 40%);">+        .id = STR_TEXT,</span><br><span style="color: hsl(120, 100%, 40%);">+        .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,</span><br><span style="color: hsl(120, 100%, 40%);">+        .create_outgoing_sdp_stream = create_outgoing_sdp_stream,</span><br><span style="color: hsl(120, 100%, 40%);">+        .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,</span><br><span style="color: hsl(120, 100%, 40%);">+        .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,</span><br><span style="color: hsl(120, 100%, 40%);">+        .stream_stop = stream_stop,</span><br><span style="color: hsl(120, 100%, 40%);">+        .stream_destroy = stream_destroy,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int video_info_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)</span><br><span> {</span><br><span>   struct pjsip_transaction *tsx;</span><br><span>@@ -2143,6 +2186,7 @@</span><br><span>       ast_sip_session_unregister_supplement(&video_info_supplement);</span><br><span>   ast_sip_session_unregister_sdp_handler(&video_sdp_handler, STR_VIDEO);</span><br><span>   ast_sip_session_unregister_sdp_handler(&audio_sdp_handler, STR_AUDIO);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_sip_session_unregister_sdp_handler(&text_sdp_handler, STR_TEXT);</span><br><span> </span><br><span>         if (sched) {</span><br><span>                 ast_sched_context_destroy(sched);</span><br><span>@@ -2189,6 +2233,11 @@</span><br><span>           goto end;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_sip_session_register_sdp_handler(&text_sdp_handler, STR_TEXT)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_log(LOG_ERROR, "Unable to register SDP handler for %s stream type\n", STR_TEXT);</span><br><span style="color: hsl(120, 100%, 40%);">+        goto end;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+        </span><br><span>     ast_sip_session_register_supplement(&video_info_supplement);</span><br><span> </span><br><span>         return AST_MODULE_LOAD_SUCCESS;</span><br><span>diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c</span><br><span>index f6b9fa9..3de2dad 100644</span><br><span>--- a/res/res_pjsip_session.c</span><br><span>+++ b/res/res_pjsip_session.c</span><br><span>@@ -545,6 +545,7 @@</span><br><span>               return (type_streams[type] > 0);</span><br><span>  case AST_MEDIA_TYPE_UNKNOWN:</span><br><span>         case AST_MEDIA_TYPE_TEXT:</span><br><span style="color: hsl(120, 100%, 40%);">+             return !(type_streams[type] < endpoint->media.max_text_streams);</span><br><span>       default:</span><br><span>             /* We don't want any unknown or "other" streams on our endpoint,</span><br><span>                * so always just say we've reached the limit</span><br><span>diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c</span><br><span>index c870fce..ec1067f 100644</span><br><span>--- a/res/res_rtp_asterisk.c</span><br><span>+++ b/res/res_rtp_asterisk.c</span><br><span>@@ -7128,9 +7128,10 @@</span><br><span>              *data++ = 0xEF;</span><br><span>              *data++ = 0xBF;</span><br><span>              *data = 0xBD;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_format_cmp(rtp->f.subclass.format, ast_format_t140_red) == AST_FORMAT_CMP_EQUAL) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if(rtp->f.datalen <= 0)   {</span><br><span style="color: hsl(120, 100%, 40%);">+                     return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (ast_format_cmp(rtp->f.subclass.format, ast_format_t140_red) == AST_FORMAT_CMP_EQUAL) {</span><br><span>                 unsigned char *data = rtp->f.data.ptr;</span><br><span>            unsigned char *header_end;</span><br><span>           int num_generations;</span><br><span>@@ -7175,6 +7176,9 @@</span><br><span>                         rtp->f.data.ptr += len;</span><br><span>                   rtp->f.datalen -= len;</span><br><span>            }</span><br><span style="color: hsl(120, 100%, 40%);">+             if(rtp->f.datalen < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span>    }</span><br><span> </span><br><span>        if (ast_format_get_type(rtp->f.subclass.format) == AST_MEDIA_TYPE_AUDIO) {</span><br><span>@@ -8056,9 +8060,12 @@</span><br><span> {</span><br><span>  struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;</span><br><span>         struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);</span><br><span style="color: hsl(120, 100%, 40%);">+    if(!rtp || !rtp->red) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return (0);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span> </span><br><span>        ao2_lock(instance);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (rtp->red->t140.datalen > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rtp && rtp->red && rtp->red->t140.datalen > 0) {</span><br><span>             ast_rtp_write(instance, &rtp->red->t140);</span><br><span>  }</span><br><span>    ao2_unlock(instance);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/13451">change 13451</a>. To unsubscribe, or for help writing mail filters, 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/c/asterisk/+/13451"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-Change-Id: I6b2ad94a065680ae9c4c933d338989e4b8c3a505 </div>
<div style="display:none"> Gerrit-Change-Number: 13451 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Bharat Ramaswamy-Nandakumar <bharat@indigital.net> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>