Should have caught this in the review, but do you mind updating the CHANGES file for this as well? :-)
On Mon, Nov 3, 2014 at 8:45 AM, SVN commits to the Asterisk project <asterisk-comm...@lists.digium.com> wrote: > Author: file > Date: Mon Nov 3 08:45:01 2014 > New Revision: 427112 > > URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=427112 > Log: > chan_pjsip: Add support for passing hold and unhold requests through. > > This change adds an option, moh_passthrough, that when enabled will pass > hold and unhold requests through using a SIP re-invite. When placing on > hold a re-invite with sendonly will be sent and when taking off hold a > re-invite with sendrecv will be sent. This allows remote servers to handle > the musiconhold instead of the local Asterisk instance being responsible. > > Review: https://reviewboard.asterisk.org/r/4103/ > > Added: > > trunk/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py > (with props) > Modified: > trunk/channels/chan_pjsip.c > trunk/channels/pjsip/dialplan_functions.c > trunk/configs/samples/pjsip.conf.sample > trunk/include/asterisk/res_pjsip.h > trunk/include/asterisk/res_pjsip_session.h > trunk/res/res_pjsip.c > trunk/res/res_pjsip/pjsip_configuration.c > trunk/res/res_pjsip_sdp_rtp.c > > Modified: trunk/channels/chan_pjsip.c > URL: > http://svnview.digium.com/svn/asterisk/trunk/channels/chan_pjsip.c?view=diff&rev=427112&r1=427111&r2=427112 > ============================================================================== > --- trunk/channels/chan_pjsip.c (original) > +++ trunk/channels/chan_pjsip.c Mon Nov 3 08:45:01 2014 > @@ -1097,6 +1097,39 @@ > return 0; > } > > +/*! \brief Callback which changes the value of locally held on the media > stream */ > +static int local_hold_set_state(void *obj, void *arg, int flags) > +{ > + struct ast_sip_session_media *session_media = obj; > + unsigned int *held = arg; > + > + session_media->locally_held = *held; > + > + return 0; > +} > + > +/*! \brief Update local hold state and send a re-INVITE with the new SDP */ > +static int remote_send_hold_refresh(struct ast_sip_session *session, > unsigned int held) > +{ > + ao2_callback(session->media, OBJ_NODATA, local_hold_set_state, &held); > + ast_sip_session_refresh(session, NULL, NULL, NULL, > AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1); > + ao2_ref(session, -1); > + > + return 0; > +} > + > +/*! \brief Update local hold state to be held */ > +static int remote_send_hold(void *data) > +{ > + return remote_send_hold_refresh(data, 1); > +} > + > +/*! \brief Update local hold state to be unheld */ > +static int remote_send_unhold(void *data) > +{ > + return remote_send_hold_refresh(data, 0); > +} > + > /*! \brief Function called by core to ask the channel to indicate some sort > of condition */ > static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const > void *data, size_t datalen) > { > @@ -1219,7 +1252,15 @@ > device_buf = alloca(device_buf_size); > ast_channel_get_device_name(ast, device_buf, device_buf_size); > ast_devstate_changed_literal(AST_DEVICE_ONHOLD, 1, > device_buf); > - ast_moh_start(ast, data, NULL); > + if (!channel->session->endpoint->moh_passthrough) { > + ast_moh_start(ast, data, NULL); > + } else { > + if (ast_sip_push_task(channel->session->serializer, > remote_send_hold, ao2_bump(channel->session))) { > + ast_log(LOG_WARNING, "Could not queue task to > remotely put session '%s' on hold with endpoint '%s'\n", > + > ast_sorcery_object_get_id(channel->session), > ast_sorcery_object_get_id(channel->session->endpoint)); > + ao2_ref(channel->session, -1); > + } > + } > break; > case AST_CONTROL_UNHOLD: > chan_pjsip_remove_hold(ast_channel_uniqueid(ast)); > @@ -1227,7 +1268,15 @@ > device_buf = alloca(device_buf_size); > ast_channel_get_device_name(ast, device_buf, device_buf_size); > ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, 1, > device_buf); > - ast_moh_stop(ast); > + if (!channel->session->endpoint->moh_passthrough) { > + ast_moh_stop(ast); > + } else { > + if (ast_sip_push_task(channel->session->serializer, > remote_send_unhold, ao2_bump(channel->session))) { > + ast_log(LOG_WARNING, "Could not queue task to > remotely take session '%s' off hold with endpoint '%s'\n", > + > ast_sorcery_object_get_id(channel->session), > ast_sorcery_object_get_id(channel->session->endpoint)); > + ao2_ref(channel->session, -1); > + } > + } > break; > case AST_CONTROL_SRCUPDATE: > break; > > Modified: trunk/channels/pjsip/dialplan_functions.c > URL: > http://svnview.digium.com/svn/asterisk/trunk/channels/pjsip/dialplan_functions.c?view=diff&rev=427112&r1=427111&r2=427112 > ============================================================================== > --- trunk/channels/pjsip/dialplan_functions.c (original) > +++ trunk/channels/pjsip/dialplan_functions.c Mon Nov 3 08:45:01 2014 > @@ -434,7 +434,7 @@ > } else if (!strcmp(type, "secure")) { > snprintf(buf, buflen, "%d", media->srtp ? 1 : 0); > } else if (!strcmp(type, "hold")) { > - snprintf(buf, buflen, "%d", media->held ? 1 : 0); > + snprintf(buf, buflen, "%d", media->remotely_held ? 1 : 0); > } else { > ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified > for 'rtp' information\n", type); > return -1; > > Modified: trunk/configs/samples/pjsip.conf.sample > URL: > http://svnview.digium.com/svn/asterisk/trunk/configs/samples/pjsip.conf.sample?view=diff&rev=427112&r1=427111&r2=427112 > ============================================================================== > --- trunk/configs/samples/pjsip.conf.sample (original) > +++ trunk/configs/samples/pjsip.conf.sample Mon Nov 3 08:45:01 2014 > @@ -616,6 +616,8 @@ > ; (default: "user") > ;mailboxes= ; Mailbox es to be associated with (default: "") > ;moh_suggest=default ; Default Music On Hold class (default: "default") > +;moh_passthrough=yes ; Pass Music On Hold through using SIP re-invites > with sendonly > + ; when placing on hold and sendrecv when taking off > hold > ;outbound_auth= ; Authentication object used for outbound requests (default: > ; "") > ;outbound_proxy= ; Proxy through which to send requests a full SIP URI > > Added: > trunk/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py > URL: > http://svnview.digium.com/svn/asterisk/trunk/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py?view=auto&rev=427112 > ============================================================================== > --- > trunk/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py > (added) > +++ > trunk/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py > Mon Nov 3 08:45:01 2014 > @@ -1,0 +1,30 @@ > +"""Add moh_passthrough option to pjsip > + > +Revision ID: 339e1dfa644d > +Revises: 1443687dda65 > +Create Date: 2014-10-21 14:55:34.197448 > + > +""" > + > +# revision identifiers, used by Alembic. > +revision = '339e1dfa644d' > +down_revision = '1443687dda65' > + > +from alembic import op > +import sqlalchemy as sa > +from sqlalchemy.dialects.postgresql import ENUM > + > +YESNO_NAME = 'yesno_values' > +YESNO_VALUES = ['yes', 'no'] > + > +def upgrade(): > + ############################# Enums ############################## > + > + # yesno_values have already been created, so use postgres enum object > + # type to get around "already created" issue - works okay with mysql > + yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False) > + > + op.add_column('ps_endpoints', sa.Column('moh_passthrough', yesno_values)) > + > +def downgrade(): > + op.drop_column('ps_endpoints', 'moh_passthrough') > > Propchange: > trunk/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py > ------------------------------------------------------------------------------ > svn:eol-style = native > > Propchange: > trunk/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py > ------------------------------------------------------------------------------ > svn:keywords = Author Date Id Revision > > Propchange: > trunk/contrib/ast-db-manage/config/versions/339e1dfa644d_add_moh_passthrough_option_to_pjsip.py > ------------------------------------------------------------------------------ > svn:mime-type = text/plain > > Modified: trunk/include/asterisk/res_pjsip.h > URL: > http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/res_pjsip.h?view=diff&rev=427112&r1=427111&r2=427112 > ============================================================================== > --- trunk/include/asterisk/res_pjsip.h (original) > +++ trunk/include/asterisk/res_pjsip.h Mon Nov 3 08:45:01 2014 > @@ -609,6 +609,8 @@ > struct ast_variable *channel_vars; > /*! Whether to place a 'user=phone' parameter into the request URI if > user is a number */ > unsigned int usereqphone; > + /*! Whether to pass through hold and unhold using re-invites with > recvonly and sendrecv */ > + unsigned int moh_passthrough; > }; > > /*! > > Modified: trunk/include/asterisk/res_pjsip_session.h > URL: > http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/res_pjsip_session.h?view=diff&rev=427112&r1=427111&r2=427112 > ============================================================================== > --- trunk/include/asterisk/res_pjsip_session.h (original) > +++ trunk/include/asterisk/res_pjsip_session.h Mon Nov 3 08:45:01 2014 > @@ -75,8 +75,10 @@ > struct ast_sdp_srtp *srtp; > /*! \brief The media transport in use for this stream */ > pj_str_t transport; > - /*! \brief Stream is on hold */ > - unsigned int held:1; > + /*! \brief Stream is on hold by remote side */ > + unsigned int remotely_held:1; > + /*! \brief Stream is on hold by local side */ > + unsigned int locally_held:1; > /*! \brief Stream type this session media handles */ > char stream_type[1]; > }; > > Modified: trunk/res/res_pjsip.c > URL: > http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip.c?view=diff&rev=427112&r1=427111&r2=427112 > ============================================================================== > --- trunk/res/res_pjsip.c (original) > +++ trunk/res/res_pjsip.c Mon Nov 3 08:45:01 2014 > @@ -576,6 +576,9 @@ > <configOption name="user_eq_phone" > default="no"> > <synopsis>Determines whether a > user=phone parameter is placed into the request URI if the user is determined > to be a phone number</synopsis> > </configOption> > + <configOption name="moh_passthrough" > default="no"> > + <synopsis>Determines whether hold and > unhold will be passed through using re-INVITEs with recvonly and sendrecv to > the remote side</synopsis> > + </configOption> > <configOption name="sdp_owner" default="-"> > <synopsis>String placed as the > username portion of an SDP origin (o=) line.</synopsis> > </configOption> > @@ -1559,6 +1562,9 @@ > </parameter> > <parameter name="UserEqPhone"> > <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> > + </parameter> > + <parameter name="MohPassthrough"> > + <para><xi:include > xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='moh_passthrough']/synopsis/node())"/></para> > </parameter> > <parameter name="SdpOwner"> > <para><xi:include > xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='sdp_owner']/synopsis/node())"/></para> > > Modified: trunk/res/res_pjsip/pjsip_configuration.c > URL: > http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip/pjsip_configuration.c?view=diff&rev=427112&r1=427111&r2=427112 > ============================================================================== > --- trunk/res/res_pjsip/pjsip_configuration.c (original) > +++ trunk/res/res_pjsip/pjsip_configuration.c Mon Nov 3 08:45:01 2014 > @@ -1733,6 +1733,7 @@ > ast_sorcery_object_field_register(sip_sorcery, "endpoint", > "record_off_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct > ast_sip_endpoint, info.recording.offfeature)); > ast_sorcery_object_field_register(sip_sorcery, "endpoint", > "allow_transfer", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, > allowtransfer)); > ast_sorcery_object_field_register(sip_sorcery, "endpoint", > "user_eq_phone", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, > usereqphone)); > + ast_sorcery_object_field_register(sip_sorcery, "endpoint", > "moh_passthrough", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, > moh_passthrough)); > ast_sorcery_object_field_register(sip_sorcery, "endpoint", > "sdp_owner", "-", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, > media.sdpowner)); > ast_sorcery_object_field_register(sip_sorcery, "endpoint", > "sdp_session", "Asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct > ast_sip_endpoint, media.sdpsession)); > ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", > "tos_audio", "0", tos_handler, tos_audio_to_str, NULL, 0, 0); > > Modified: trunk/res/res_pjsip_sdp_rtp.c > URL: > http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip_sdp_rtp.c?view=diff&rev=427112&r1=427111&r2=427112 > ============================================================================== > --- trunk/res/res_pjsip_sdp_rtp.c (original) > +++ trunk/res/res_pjsip_sdp_rtp.c Mon Nov 3 08:45:01 2014 > @@ -887,6 +887,7 @@ > static const pj_str_t STR_IP4 = { "IP4", 3}; > static const pj_str_t STR_IP6 = { "IP6", 3}; > static const pj_str_t STR_SENDRECV = { "sendrecv", 8 }; > + static const pj_str_t STR_SENDONLY = { "sendonly", 8 }; > pjmedia_sdp_media *media; > char hostip[PJ_INET6_ADDRSTRLEN+2]; > struct ast_sockaddr addr; > @@ -1046,7 +1047,7 @@ > > /* Add the sendrecv attribute - we purposely don't keep track because > pjmedia-sdp will automatically change our offer for us */ > attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr); > - attr->name = STR_SENDRECV; > + attr->name = !session_media->locally_held ? STR_SENDRECV : > STR_SENDONLY; > media->attr[media->attr_count++] = attr; > > /* Add the media stream to the SDP */ > @@ -1122,18 +1123,18 @@ > if (ast_sockaddr_isnull(addrs) || > ast_sockaddr_is_any(addrs) || > pjmedia_sdp_media_find_attr2(remote_stream, "sendonly", > NULL)) { > - if (!session_media->held) { > + if (!session_media->remotely_held) { > /* The remote side has put us on hold */ > ast_queue_hold(session->channel, > session->endpoint->mohsuggest); > ast_rtp_instance_stop(session_media->rtp); > ast_queue_frame(session->channel, &ast_null_frame); > - session_media->held = 1; > - } > - } else if (session_media->held) { > + session_media->remotely_held = 1; > + } > + } else if (session_media->remotely_held) { > /* The remote side has taken us off hold */ > ast_queue_unhold(session->channel); > ast_queue_frame(session->channel, &ast_null_frame); > - session_media->held = 0; > + session_media->remotely_held = 0; > } > > return 1; > > > -- > _____________________________________________________________________ > -- Bandwidth and Colocation Provided by http://www.api-digital.com -- > > asterisk-commits mailing list > To UNSUBSCRIBE or update options visit: > http://lists.digium.com/mailman/listinfo/asterisk-commits -- Matthew Jordan Digium, Inc. | Engineering Manager 445 Jan Davis Drive NW - Huntsville, AL 35806 - USA Check us out at: http://digium.com & http://asterisk.org -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- asterisk-dev mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/asterisk-dev