; 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]
--- /dev/null
+"""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')
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 */
<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>
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");
if (session_media->remotely_held_changed) {
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);
+ 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 */
- ast_queue_unhold(session->channel);
- ast_queue_frame(session->channel, &ast_null_frame);
+ 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)