res_pjsip: Add new endpoint option "suppress_moh_on_sendonly"

Normally, when one party in a call sends Asterisk an SDP with
a "sendonly" or "inactive" attribute it means "hold" and causes
Asterisk to start playing MOH back to the other party. This can be
problematic if it happens at certain times, such as in a 183
Progress message, because the MOH will replace any early media you
may be playing to the calling party. If you set this option
to "yes" on an endpoint and the endpoint receives an SDP
with "sendonly" or "inactive", Asterisk will NOT play MOH back to
the other party.

Resolves: #979

UserNote: The new "suppress_moh_on_sendonly" endpoint option
can be used to prevent playing MOH back to a caller if the remote
end sends "sendonly" or "inactive" (hold) to Asterisk in an SDP.
pull/994/head
George Joseph 6 months ago committed by asterisk-org-access-app[bot]
parent db79bcb82f
commit 02e2000653

@ -1015,7 +1015,21 @@
; using the same CHANNEL function if needed. Setting tenant ID here
; will cause it to show up on channel creation and the initial
; channel snapshot.
;
; suppress_moh_on_sendonly = no
; Normally, when one party in a call sends Asterisk an SDP with
; a "sendonly" or "inactive" attribute it means "hold" and
; causes Asterisk to start playing MOH back to the other party.
; This can be problematic if it happens at certain times, such
; as in a 183 Progress message, because the MOH will replace
; any early media you may be playing to the calling party. If
; you set this option to "yes" on an endpoint and the endpoint
; receives an SDP with "sendonly" or "inactive", Asterisk will
; NOT play MOH back to the other party.
; NOTE: This doesn't just apply to 183 responses. MOH will
; be suppressed when the attribute appears in any SDP received
; including INVITEs, re-INVITES, and other responses.
; (default: no)
;==========================AUTH SECTION OPTIONS=========================
;[auth]

@ -0,0 +1,30 @@
"""Add suppress_moh_on_sendonly
Revision ID: 4f91fc18c979
Revises: 801b9fced8b7
Create Date: 2024-11-05 11:37:33.604448
"""
# revision identifiers, used by Alembic.
revision = '4f91fc18c979'
down_revision = '801b9fced8b7'
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import ENUM
YESNO_NAME = 'yesno_values'
YESNO_VALUES = ['yes', 'no']
def upgrade():
yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
op.add_column('ps_endpoints', sa.Column('suppress_moh_on_sendonly', yesno_values))
def downgrade():
if op.get_context().bind.dialect.name == 'mssql':
op.drop_constraint('ck_ps_endpoints_suppress_moh_on_sendonly_yesno_values', 'ps_endpoints')
op.drop_column('ps_endpoints', 'suppress_moh_on_sendonly')

@ -1069,6 +1069,8 @@ struct ast_sip_endpoint {
unsigned int send_aoc;
/*! Tenant ID for the endpoint */
AST_STRING_FIELD_EXTENDED(tenantid);
/*! Ignore remote hold requests */
int suppress_moh_on_sendonly;
};
/*! URI parameter for symmetric transport */

@ -1533,6 +1533,27 @@
<configOption name="send_aoc" default="no">
<synopsis>Send Advice-of-Charge messages</synopsis>
</configOption>
<configOption name="suppress_moh_on_sendonly" default="no">
<synopsis>Suppress playing MOH to party A if party B sends
"sendonly" or "inactive" in an SDP</synopsis>
<description><para>
Normally, when one party in a call sends Asterisk an SDP with a "sendonly"
or "inactive" attribute it means "hold" and causes Asterisk to start
playing MOH back to the other party. This can be problematic if it happens at
certain times, such as in a 183 Progress message, because the MOH will
replace any early media you may be playing to the calling party. If you set
this option to "yes" on an endpoint and the endpoint receives an SDP
with "sendonly" or "inactive", Asterisk will NOT play MOH back to the other
party.
</para>
<note><para>
This doesn't just apply to 183 responses. MOH will be suppressed when
the attribute appears in any SDP received including INVITEs, re-INVITES,
and other responses.
</para>
</note>
</description>
</configOption>
</configObject>
<configObject name="auth">
<synopsis>Authentication type</synopsis>

@ -2304,6 +2304,8 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "security_negotiation", "no", security_negotiation_handler, security_negotiation_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "send_aoc", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, send_aoc));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tenantid", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, tenantid));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "suppress_moh_on_sendonly",
"no", OPT_YESNO_T, 1, FLDSET(struct ast_sip_endpoint, suppress_moh_on_sendonly));
if (ast_sip_initialize_sorcery_transport()) {
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");

@ -2321,14 +2321,18 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session,
if (session_media->remotely_held_changed) {
if (session_media->remotely_held) {
/* The remote side has put us on hold */
if (!session->endpoint->suppress_moh_on_sendonly) {
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->remotely_held_changed = 0;
} else {
/* The remote side has taken us off hold */
if (!session->endpoint->suppress_moh_on_sendonly) {
ast_queue_unhold(session->channel);
ast_queue_frame(session->channel, &ast_null_frame);
}
session_media->remotely_held_changed = 0;
}
} else if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)

Loading…
Cancel
Save