<p>Torrey Searle would like Joshua Colp to <strong>review</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/12891">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_pjsip: Add support for passing hold and unhold requests through.<br><br>This change adds an option, moh_passthrough, that when enabled will pass<br>hold and unhold requests through using a SIP re-invite. When placing on<br>hold a re-invite with sendonly will be sent and when taking off hold a<br>re-invite with sendrecv will be sent. This allows remote servers to handle<br>the musiconhold instead of the local Asterisk instance being responsible.<br><br>Review: https://reviewboard.asterisk.org/r/4103/<br><br>Change-Id: Ib6294e906e577e1a4245cb1f058d3976ff484c52<br>---<br>M channels/chan_pjsip.c<br>M channels/pjsip/dialplan_functions.c<br>M configs/samples/pjsip.conf.sample<br>A contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.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, 107 insertions(+), 14 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/91/12891/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..2a243b6 100644</span><br><span>--- a/channels/chan_pjsip.c</span><br><span>+++ b/channels/chan_pjsip.c</span><br><span>@@ -1349,6 +1349,39 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Callback which changes the value of locally held on the media stream */</span><br><span style="color: hsl(120, 100%, 40%);">+static int local_hold_set_state(void *obj, void *arg, int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_sip_session_media *session_media = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int *held = arg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ session_media->locally_held = *held;</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 style="color: hsl(120, 100%, 40%);">+/*! \brief Update local hold state and send a re-INVITE with the new SDP */</span><br><span style="color: hsl(120, 100%, 40%);">+static int remote_send_hold_refresh(struct ast_sip_session *session, unsigned int held)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_callback(session->media, OBJ_NODATA, local_hold_set_state, &held);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sip_session_refresh(session, NULL, NULL, NULL, AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(session, -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 style="color: hsl(120, 100%, 40%);">+/*! \brief Update local hold state to be held */</span><br><span style="color: hsl(120, 100%, 40%);">+static int remote_send_hold(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return remote_send_hold_refresh(data, 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%);">+/*! \brief Update local hold state to be unheld */</span><br><span style="color: hsl(120, 100%, 40%);">+static int remote_send_unhold(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return remote_send_hold_refresh(data, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief Function called by core to ask the channel to indicate some sort of condition */</span><br><span> static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)</span><br><span> {</span><br><span>@@ -1493,7 +1526,15 @@</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->endpoint->moh_passthrough) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_moh_start(ast, data, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_sip_push_task(channel->session->serializer, remote_send_hold, ao2_bump(channel->session))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Could not queue task to remotely put session '%s' on hold with endpoint '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_get_id(channel->session), ast_sorcery_object_get_id(channel->session->endpoint));</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(channel->session, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</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 +1542,15 @@</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->endpoint->moh_passthrough) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_moh_stop(ast);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_sip_push_task(channel->session->serializer, remote_send_unhold, ao2_bump(channel->session))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Could not queue task to remotely take session '%s' off hold with endpoint '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_get_id(channel->session), ast_sorcery_object_get_id(channel->session->endpoint));</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(channel->session, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</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>diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c</span><br><span>index 76f351f..6cdc721 100644</span><br><span>--- a/channels/pjsip/dialplan_functions.c</span><br><span>+++ b/channels/pjsip/dialplan_functions.c</span><br><span>@@ -592,7 +592,7 @@</span><br><span> snprintf(buf, buflen, "%d", 0);</span><br><span> }</span><br><span> } else if (!strcmp(type, "hold")) {</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(buf, buflen, "%d", media->held ? 1 : 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(buf, buflen, "%d", media->remotely_held ? 1 : 0);</span><br><span> } else {</span><br><span> ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified for 'rtp' information\n", type);</span><br><span> return -1;</span><br><span>diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample</span><br><span>index bbd0317..9e6365e 100644</span><br><span>--- a/configs/samples/pjsip.conf.sample</span><br><span>+++ b/configs/samples/pjsip.conf.sample</span><br><span>@@ -655,6 +655,8 @@</span><br><span> ; An MWI subscribe will replace unsoliticed NOTIFYs</span><br><span> ; (default: "no")</span><br><span> ;moh_suggest=default ; Default Music On Hold class (default: "default")</span><br><span style="color: hsl(120, 100%, 40%);">+;moh_passthrough=yes ; Pass Music On Hold through using SIP re-invites with sendonly</span><br><span style="color: hsl(120, 100%, 40%);">+ ; when placing on hold and sendrecv when taking off hold</span><br><span> ;outbound_auth= ; Authentication object used for outbound requests (default:</span><br><span> ; "")</span><br><span> ;outbound_proxy= ; Proxy through which to send requests, a full SIP URI</span><br><span>diff --git a/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py b/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py</span><br><span>new file mode 100644</span><br><span>index 0000000..d3ee2e5</span><br><span>--- /dev/null</span><br><span>+++ b/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py</span><br><span>@@ -0,0 +1,30 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""Add moh_passthrough option to pjsip</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Revision ID: 339e1dfa644d</span><br><span style="color: hsl(120, 100%, 40%);">+Revises: 1443687dda65</span><br><span style="color: hsl(120, 100%, 40%);">+Create Date: 2014-10-21 14:55:34.197448</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 = '339e1dfa644d'</span><br><span style="color: hsl(120, 100%, 40%);">+down_revision = '1443687dda65'</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%);">+YESNO_NAME = 'yesno_values'</span><br><span style="color: hsl(120, 100%, 40%);">+YESNO_VALUES = ['yes', 'no']</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%);">+ yesno_values = ENUM(*YESNO_VALUES, name=YESNO_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('moh_passthrough', yesno_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%);">+ op.drop_column('ps_endpoints', 'moh_passthrough')</span><br><span>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h</span><br><span>index 5e8dd3a..54977d1 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -768,6 +768,7 @@</span><br><span> struct ast_variable *channel_vars;</span><br><span> /*! Whether to place a 'user=phone' parameter into the request URI if user is a number */</span><br><span> unsigned int usereqphone;</span><br><span style="color: hsl(120, 100%, 40%);">+<<<<<<< HEAD</span><br><span> /*! Do we send messages for connected line updates for unanswered incoming calls immediately to this endpoint? */</span><br><span> unsigned int rpid_immediate;</span><br><span> /*! Access control list */</span><br><span>@@ -802,6 +803,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%);">+ /*! Whether to pass through hold and unhold using re-invites with recvonly and sendrecv */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int moh_passthrough;</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..51d75c6 100644</span><br><span>--- a/include/asterisk/res_pjsip_session.h</span><br><span>+++ b/include/asterisk/res_pjsip_session.h</span><br><span>@@ -81,8 +81,10 @@</span><br><span> int keepalive_sched_id;</span><br><span> /*! \brief Scheduler ID for RTP timeout */</span><br><span> int timeout_sched_id;</span><br><span style="color: hsl(0, 100%, 40%);">- /*! \brief Stream is on hold */</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int held:1;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! \brief Stream is on hold by remote side */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int remotely_held:1;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! \brief Stream is on hold by local side */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int locally_held:1;</span><br><span> /*! \brief Does remote support rtcp_mux */</span><br><span> unsigned int remote_rtcp_mux:1;</span><br><span> /*! \brief Does remote support ice */</span><br><span>diff --git a/res/res_pjsip.c b/res/res_pjsip.c</span><br><span>index c41b545..ec159d6 100644</span><br><span>--- a/res/res_pjsip.c</span><br><span>+++ b/res/res_pjsip.c</span><br><span>@@ -744,6 +744,9 @@</span><br><span> <configOption name="user_eq_phone" default="no"></span><br><span> <synopsis>Determines whether a user=phone parameter is placed into the request URI if the user is determined to be a phone number</synopsis></span><br><span> </configOption></span><br><span style="color: hsl(120, 100%, 40%);">+ <configOption name="moh_passthrough" default="no"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis>Determines whether hold and unhold will be passed through using re-INVITEs with recvonly and sendrecv to the remote side</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ </configOption></span><br><span> <configOption name="sdp_owner" default="-"></span><br><span> <synopsis>String placed as the username portion of an SDP origin (o=) line.</synopsis></span><br><span> </configOption></span><br><span>@@ -2286,6 +2289,9 @@</span><br><span> <parameter name="UserEqPhone"></span><br><span> <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='user_eq_phone']/synopsis/node())"/></para></span><br><span> </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="MohPassthrough"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='moh_passthrough']/synopsis/node())"/></para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span> <parameter name="SdpOwner"></span><br><span> <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='sdp_owner']/synopsis/node())"/></para></span><br><span> </parameter></span><br><span>diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c</span><br><span>index b5525be..db53592 100644</span><br><span>--- a/res/res_pjsip/pjsip_configuration.c</span><br><span>+++ b/res/res_pjsip/pjsip_configuration.c</span><br><span>@@ -1858,6 +1858,7 @@</span><br><span> ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_off_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.offfeature));</span><br><span> ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_transfer", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allowtransfer));</span><br><span> ast_sorcery_object_field_register(sip_sorcery, "endpoint", "user_eq_phone", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, usereqphone));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "moh_passthrough", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, moh_passthrough));</span><br><span> ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_owner", "-", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpowner));</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>diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c</span><br><span>index 76d47a3..b3be455 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>@@ -1369,7 +1370,7 @@</span><br><span> </span><br><span> /* 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%);">+ attr->name = !session_media->locally_held ? STR_SENDRECV : STR_SENDONLY;</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>@@ -1469,20 +1470,19 @@</span><br><span> </span><br><span> if (ast_sockaddr_isnull(addrs) ||</span><br><span> ast_sockaddr_is_any(addrs) ||</span><br><span style="color: hsl(0, 100%, 40%);">- pjmedia_sdp_media_find_attr2(remote_stream, "sendonly", NULL) ||</span><br><span style="color: hsl(0, 100%, 40%);">- pjmedia_sdp_media_find_attr2(remote_stream, "inactive", NULL)) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (!session_media->held) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pjmedia_sdp_media_find_attr2(remote_stream, "sendonly", NULL)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!session_media->remotely_held) {</span><br><span> /* The remote side has put us on hold */</span><br><span> ast_queue_hold(session->channel, session->endpoint->mohsuggest);</span><br><span> ast_rtp_instance_stop(session_media->rtp);</span><br><span> ast_queue_frame(session->channel, &ast_null_frame);</span><br><span style="color: hsl(0, 100%, 40%);">- session_media->held = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ session_media->remotely_held = 1;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (session_media->held) {</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (session_media->remotely_held) {</span><br><span> /* The remote side has taken us off hold */</span><br><span> ast_queue_unhold(session->channel);</span><br><span> ast_queue_frame(session->channel, &ast_null_frame);</span><br><span style="color: hsl(0, 100%, 40%);">- session_media->held = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ session_media->remotely_held = 0;</span><br><span> } else if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)</span><br><span> && (session->inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {</span><br><span> ast_queue_control(session->channel, AST_CONTROL_UPDATE_RTP_PEER);</span><br><span>@@ -1513,9 +1513,9 @@</span><br><span> * instance itself.</span><br><span> */</span><br><span> ast_rtp_instance_set_timeout(session_media->rtp, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- if (session->endpoint->media.rtp.timeout && !session_media->held) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (session->endpoint->media.rtp.timeout && !session_media->remotely_held) {</span><br><span> ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (session->endpoint->media.rtp.timeout_hold && session_media->held) {</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (session->endpoint->media.rtp.timeout_hold && session_media->remotely_held) {</span><br><span> ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout_hold);</span><br><span> }</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/12891">change 12891</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/+/12891"/><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: Ib6294e906e577e1a4245cb1f058d3976ff484c52 </div>
<div style="display:none"> Gerrit-Change-Number: 12891 </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-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>