]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip: Add new endpoint option "suppress_moh_on_sendonly"
authorGeorge Joseph <gjoseph@sangoma.com>
Tue, 5 Nov 2024 18:30:55 +0000 (11:30 -0700)
committerGeorge Joseph <gjoseph@sangoma.com>
Wed, 13 Nov 2024 16:06:48 +0000 (16:06 +0000)
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.

configs/samples/pjsip.conf.sample
contrib/ast-db-manage/config/versions/4f91fc18c979_add_suppress_moh_on_sendonly.py [new file with mode: 0644]
include/asterisk/res_pjsip.h
res/res_pjsip/pjsip_config.xml
res/res_pjsip/pjsip_configuration.c
res/res_pjsip_sdp_rtp.c

index 0e2f283ea0e52f0812cb1c94e3611e3dd83909bd..32af1b2d131622c02644d1ad2876051602b14e91 100644 (file)
                 ; 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]
diff --git a/contrib/ast-db-manage/config/versions/4f91fc18c979_add_suppress_moh_on_sendonly.py b/contrib/ast-db-manage/config/versions/4f91fc18c979_add_suppress_moh_on_sendonly.py
new file mode 100644 (file)
index 0000000..fb6a3ef
--- /dev/null
@@ -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')
index 46e376325c51d6353816b4e7dd2a59f1ae6e9b0c..cdc71a5f74ec20d047eec0a9cfd5ce5c374d908c 100644 (file)
@@ -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 */
index ab1c6332f3852521e1817ebcbf2583aa178fb572..71c73dc2ae0389811a37aec3414d394f2444c76e 100644 (file)
                                <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>
index c6f4d83b383ede54feed17d89f81b9f7b67d70e5..8ac1d2c24031d35f14371ebbae2c0d9dde85bbf9 100644 (file)
@@ -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");
index 4423dfda5ccae1746ad00fb78199f7ff5a14676a..7d2a5e7c4acb85ce2617a98df37f80a4931d0493 100644 (file)
@@ -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 */
-                       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)