<p>Torrey Searle has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/12890">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip: Add the option to send on-hold sdp instead of MOH<br><br>Add a new endpoint config option to have asterisk generate on<br>hold re-invites when a channen is put on hold instead of<br>generating music on hold.  Additionally a new dialplan<br>function has been added so this behavior can be controlled on<br>a per-call basis<br><br>ASTERISK-28542 #close<br><br>Change-Id: Ifb23a8b61e6788647ecb77495f5acf35d88bc113<br>---<br>M channels/chan_pjsip.c<br>M channels/pjsip/dialplan_functions.c<br>M channels/pjsip/include/dialplan_functions.h<br>A contrib/ast-db-manage/config/versions/d9d244af5882_send_hold_mode.py<br>M include/asterisk/res_pjsip.h<br>M include/asterisk/res_pjsip_session.h<br>M res/res_pjsip.c<br>M res/res_pjsip/pjsip_configuration.c<br>M res/res_pjsip_sdp_rtp.c<br>9 files changed, 160 insertions(+), 5 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/90/12890/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 b0d5fda..4aa21c9 100644</span><br><span>--- a/channels/chan_pjsip.c</span><br><span>+++ b/channels/chan_pjsip.c</span><br><span>@@ -1493,7 +1493,12 @@</span><br><span>          device_buf = alloca(device_buf_size);</span><br><span>                ast_channel_get_device_name(ast, device_buf, device_buf_size);</span><br><span>               ast_devstate_changed_literal(AST_DEVICE_ONHOLD, 1, device_buf);</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_moh_start(ast, data, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (channel->session && channel->session->send_hold) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_sip_session_refresh(channel->session, NULL, NULL, NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+                                AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+            } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_moh_start(ast, data, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span>            break;</span><br><span>       case AST_CONTROL_UNHOLD:</span><br><span>             chan_pjsip_remove_hold(ast_channel_uniqueid(ast));</span><br><span>@@ -1501,7 +1506,12 @@</span><br><span>          device_buf = alloca(device_buf_size);</span><br><span>                ast_channel_get_device_name(ast, device_buf, device_buf_size);</span><br><span>               ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, 1, device_buf);</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_moh_stop(ast);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (channel->session && channel->session->send_hold) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_sip_session_refresh(channel->session, NULL, NULL, NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+                                AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+            } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_moh_stop(ast);</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span>            break;</span><br><span>       case AST_CONTROL_SRCUPDATE:</span><br><span>          break;</span><br><span>@@ -2810,6 +2820,12 @@</span><br><span>      .write = pjsip_acf_dtmf_mode_write</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_custom_function hold_mode_function = {</span><br><span style="color: hsl(120, 100%, 40%);">+        .name = "PJSIP_SEND_HOLD_MODE",</span><br><span style="color: hsl(120, 100%, 40%);">+     .read = pjsip_acf_send_hold_mode_read,</span><br><span style="color: hsl(120, 100%, 40%);">+        .write = pjsip_acf_send_hold_mode_write</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct ast_custom_function session_refresh_function = {</span><br><span>      .name = "PJSIP_SEND_SESSION_REFRESH",</span><br><span>      .write = pjsip_acf_session_refresh_write,</span><br><span>@@ -2864,6 +2880,11 @@</span><br><span>           goto end;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_custom_function_register(&hold_mode_function)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_WARNING, "Unable to register PJSIP_HOLD_MODE dialplan function\n");</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>  if (ast_custom_function_register(&session_refresh_function)) {</span><br><span>           ast_log(LOG_WARNING, "Unable to register PJSIP_SEND_SESSION_REFRESH dialplan function\n");</span><br><span>                 goto end;</span><br><span>@@ -2924,6 +2945,7 @@</span><br><span>    ast_sip_session_unregister_supplement(&chan_pjsip_supplement);</span><br><span>   ast_sip_session_unregister_supplement(&call_pickup_supplement);</span><br><span>  ast_custom_function_unregister(&dtmf_mode_function);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_custom_function_unregister(&hold_mode_function);</span><br><span>     ast_custom_function_unregister(&media_offer_function);</span><br><span>   ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);</span><br><span>      ast_custom_function_unregister(&chan_pjsip_parse_uri_function);</span><br><span>diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c</span><br><span>index 76f351f..e18f134 100644</span><br><span>--- a/channels/pjsip/dialplan_functions.c</span><br><span>+++ b/channels/pjsip/dialplan_functions.c</span><br><span>@@ -1303,6 +1303,37 @@</span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int pjsip_acf_send_hold_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_sip_channel_pvt *channel;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_channel_lock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_channel_unlock(chan);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (len < 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_WARNING, "%s: buffer too small\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_channel_unlock(chan);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ channel = ast_channel_tech_pvt(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       strncpy(buf, AST_YESNO(channel->session->send_hold), len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_channel_unlock(chan);</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> struct refresh_data {</span><br><span>      struct ast_sip_session *session;</span><br><span>     enum ast_sip_session_refresh_method method;</span><br><span>@@ -1445,6 +1476,30 @@</span><br><span>         return ast_sip_push_task_wait_serializer(channel->session->serializer, dtmf_mode_refresh_cb, &rdata);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int pjsip_acf_send_hold_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_sip_channel_pvt *channel;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!chan) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_channel_lock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_channel_unlock(chan);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   channel = ast_channel_tech_pvt(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       channel->session->send_hold = ast_true(value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_channel_unlock(chan);</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 refresh_write_cb(void *obj)</span><br><span> {</span><br><span>        struct refresh_data *data = obj;</span><br><span>diff --git a/channels/pjsip/include/dialplan_functions.h b/channels/pjsip/include/dialplan_functions.h</span><br><span>index a9332a2..e41e2f1 100644</span><br><span>--- a/channels/pjsip/include/dialplan_functions.h</span><br><span>+++ b/channels/pjsip/include/dialplan_functions.h</span><br><span>@@ -73,6 +73,31 @@</span><br><span> int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief PJSIP_SEND_HOLD function read callback</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param chan The channel the function is called on</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param cmd The name of the function</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param data Arguments passed to the function</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param buf Out buffer that should be populated with the data</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param len Size of the buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 on success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int pjsip_acf_send_hold_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);</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%);">+ * \brief PJSIP_SEND_HOLD_MODE function write callback</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param chan The channel the function is called on</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param cmd The name of the function</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param data Arguments passed to the function</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param value Value to be set by the function</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 on success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int pjsip_acf_send_hold_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \brief PJSIP_MEDIA_OFFER function read callback</span><br><span>  * \param chan The channel the function is called on</span><br><span>  * \param cmd The name of the function</span><br><span>@@ -123,4 +148,4 @@</span><br><span>  */</span><br><span> int pjsip_acf_parse_uri_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#endif /* _PJSIP_DIALPLAN_FUNCTIONS */</span><br><span>\ No newline at end of file</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* _PJSIP_DIALPLAN_FUNCTIONS */</span><br><span>diff --git a/contrib/ast-db-manage/config/versions/d9d244af5882_send_hold_mode.py b/contrib/ast-db-manage/config/versions/d9d244af5882_send_hold_mode.py</span><br><span>new file mode 100644</span><br><span>index 0000000..9428181</span><br><span>--- /dev/null</span><br><span>+++ b/contrib/ast-db-manage/config/versions/d9d244af5882_send_hold_mode.py</span><br><span>@@ -0,0 +1,38 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""send_hold_mode</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Revision ID: d9d244af5882</span><br><span style="color: hsl(120, 100%, 40%);">+Revises: 3a094a18e75b</span><br><span style="color: hsl(120, 100%, 40%);">+Create Date: 2019-09-18 08:47:46.231663</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%);">+# revision identifiers, used by Alembic.</span><br><span style="color: hsl(120, 100%, 40%);">+revision = 'd9d244af5882'</span><br><span style="color: hsl(120, 100%, 40%);">+down_revision = '3a094a18e75b'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from alembic import op</span><br><span style="color: hsl(120, 100%, 40%);">+import sqlalchemy as sa</span><br><span style="color: hsl(120, 100%, 40%);">+from sqlalchemy.dialects.postgresql import ENUM</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_BOOL_NAME = 'ast_bool_values'</span><br><span style="color: hsl(120, 100%, 40%);">+# We'll just ignore the n/y and f/t abbreviations as Asterisk does not write</span><br><span style="color: hsl(120, 100%, 40%);">+# those aliases.</span><br><span style="color: hsl(120, 100%, 40%);">+AST_BOOL_VALUES = [ '0', '1',</span><br><span style="color: hsl(120, 100%, 40%);">+                    'off', 'on',</span><br><span style="color: hsl(120, 100%, 40%);">+                    'false', 'true',</span><br><span style="color: hsl(120, 100%, 40%);">+                    'no', 'yes' ]</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%);">+def upgrade():</span><br><span style="color: hsl(120, 100%, 40%);">+    ############################# Enums ##############################</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    # yesno_values have already been created, so use postgres enum object</span><br><span style="color: hsl(120, 100%, 40%);">+    # type to get around "already created" issue - works okay with mysql</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_bool_values = ENUM(*AST_BOOL_VALUES, name=AST_BOOL_NAME, create_type=False)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    op.add_column('ps_endpoints', sa.Column('send_hold_mode', ast_bool_values))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def downgrade():</span><br><span style="color: hsl(120, 100%, 40%);">+    if op.get_context().bind.dialect.name == 'mssql':</span><br><span style="color: hsl(120, 100%, 40%);">+        op.drop_constraint('ck_ps_endpoints_send_hold_mode_ast_bool_values', 'ps_endpoints')</span><br><span style="color: hsl(120, 100%, 40%);">+    op.drop_column('ps_endpoints', 'send_hold_mode')</span><br><span>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h</span><br><span>index 5e8dd3a..91ba08e 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -802,6 +802,8 @@</span><br><span>    unsigned int send_connected_line;</span><br><span>    /*! Ignore 183 if no SDP is present */</span><br><span>       unsigned int ignore_183_without_sdp;</span><br><span style="color: hsl(120, 100%, 40%);">+  /*! Send On-Hold Re-Invite intead of music on hold */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int send_hold;</span><br><span> };</span><br><span> </span><br><span> /*! URI parameter for symmetric transport */</span><br><span>diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h</span><br><span>index e2d4fcd..4a7e9e0 100644</span><br><span>--- a/include/asterisk/res_pjsip_session.h</span><br><span>+++ b/include/asterisk/res_pjsip_session.h</span><br><span>@@ -159,6 +159,8 @@</span><br><span>         unsigned int defer_end:1;</span><br><span>    /*! Session end (remote hangup) requested while termination deferred */</span><br><span>      unsigned int ended_while_deferred:1;</span><br><span style="color: hsl(120, 100%, 40%);">+  /*! Send hold re-invite instead of music on hold */</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned int send_hold:1;</span><br><span>    /*! DTMF mode to use with this session, from endpoint but can change */</span><br><span>      enum ast_sip_dtmf_mode dtmf;</span><br><span>         /*! Initial incoming INVITE Request-URI.  NULL otherwise. */</span><br><span>diff --git a/res/res_pjsip.c b/res/res_pjsip.c</span><br><span>index c41b545..08a1c48 100644</span><br><span>--- a/res/res_pjsip.c</span><br><span>+++ b/res/res_pjsip.c</span><br><span>@@ -104,6 +104,9 @@</span><br><span>                          <configOption name="allow_overlap" default="yes"></span><br><span>                                  <synopsis>Enable RFC3578 overlap dialing support.</synopsis></span><br><span>                             </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+                         <configOption name="send_hold_mode" default="no"></span><br><span style="color: hsl(120, 100%, 40%);">+                                   <synopsis>If yes, send On-Hold Re-Invites.  If no, generate music on hold</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                              </configOption></span><br><span>                                <configOption name="aors"></span><br><span>                                   <synopsis>AoR(s) to be used with the endpoint</synopsis></span><br><span>                                         <description><para></span><br><span>diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c</span><br><span>index b5525be..5b07624 100644</span><br><span>--- a/res/res_pjsip/pjsip_configuration.c</span><br><span>+++ b/res/res_pjsip/pjsip_configuration.c</span><br><span>@@ -1904,6 +1904,7 @@</span><br><span>     ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accept_multiple_sdp_answers", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, accept_multiple_sdp_answers));</span><br><span>  ast_sorcery_object_field_register(sip_sorcery, "endpoint", "suppress_q850_reason_headers", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, suppress_q850_reason_headers));</span><br><span>        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ignore_183_without_sdp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, ignore_183_without_sdp));</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_hold_reinvite", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, send_hold));</span><br><span> </span><br><span>         if (ast_sip_initialize_sorcery_transport()) {</span><br><span>                ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");</span><br><span>diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c</span><br><span>index 76d47a3..eacf4e4 100644</span><br><span>--- a/res/res_pjsip_sdp_rtp.c</span><br><span>+++ b/res/res_pjsip_sdp_rtp.c</span><br><span>@@ -1184,6 +1184,7 @@</span><br><span>    static const pj_str_t STR_IP4 = { "IP4", 3};</span><br><span>       static const pj_str_t STR_IP6 = { "IP6", 3};</span><br><span>       static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };</span><br><span style="color: hsl(120, 100%, 40%);">+     static const pj_str_t STR_SENDONLY = { "sendonly", 8 };</span><br><span>    pjmedia_sdp_media *media;</span><br><span>    const char *hostip = NULL;</span><br><span>   struct ast_sockaddr addr;</span><br><span>@@ -1367,9 +1368,15 @@</span><br><span>           media->attr[media->attr_count++] = attr;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Add the sendrecv attribute - we purposely don't keep track because pjmedia-sdp will automatically change our offer for us */</span><br><span>  attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);</span><br><span style="color: hsl(0, 100%, 40%);">-        attr->name = STR_SENDRECV;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if(session->channel && session->send_hold && ast_channel_hold_state(session->channel)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Hint to pjmedia-sdp that we want to initate hold */</span><br><span style="color: hsl(120, 100%, 40%);">+                attr->name = STR_SENDONLY;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Else add the sendrecv attribute pjmedia-sdp will automatically change our offer for us if needed */</span><br><span style="color: hsl(120, 100%, 40%);">+                attr->name = STR_SENDRECV;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span>    media->attr[media->attr_count++] = attr;</span><br><span> </span><br><span>   /* If we've got rtcp-mux enabled, add it unless we received an offer without it */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/12890">change 12890</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/+/12890"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-Change-Id: Ifb23a8b61e6788647ecb77495f5acf35d88bc113 </div>
<div style="display:none"> Gerrit-Change-Number: 12890 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Torrey Searle <tsearle@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>