]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip_t38: bind UDPTL sessions like RTP
authorMatthew Kern <mkern@alconconstruction.com>
Mon, 19 Jul 2021 16:34:00 +0000 (10:34 -0600)
committerMatthew Kern <mkern@alconconstruction.com>
Fri, 1 Oct 2021 13:58:27 +0000 (08:58 -0500)
In res_pjsip_sdp_rtp, the bind_rtp_to_media_address option and the
fallback use of the transport's bind address solve problems sending
media on systems that cannot send ipv4 packets on ipv6 sockets, and
certain other situations. This change extends both of these behaviors
to UDPTL sessions as well in res_pjsip_t38, to fix fax-specific
problems on these systems, introducing a new option
endpoint/t38_bind_udptl_to_media_address.

ASTERISK-29402

Change-Id: I87220c0e9cdd2fe9d156846cb906debe08c63557

configs/samples/pjsip.conf.sample
contrib/ast-db-manage/config/versions/a06d8f8462d9_add_t38_bind_udptl_to_media_address.py [new file with mode: 0644]
doc/CHANGES-staging/res_pjsip_t38_bind_fixes.txt [new file with mode: 0644]
include/asterisk/res_pjsip.h
res/res_pjsip.c
res/res_pjsip/pjsip_configuration.c
res/res_pjsip_t38.c

index 80888c32ab8251f6c01275021018e881ac4431ad..2d57208e656ef6998a29d6ce0829ade15a4330ce 100644 (file)
                         ; (default: "0")
 ;t38_udptl_nat=no       ; Whether NAT support is enabled on UDPTL sessions
                         ; (default: "no")
+;t38_bind_rtp_to_media_address=     ; Bind the UDPTL session to the media_address.
+                                    ; This causes all UDPTL packets to be sent from
+                                    ; the specified address. (default: "no")
 ;tone_zone=     ; Set which country s indications to use for channels created
                 ; for this endpoint (default: "")
 ;language=      ; Set the default language to use for channels created for this
diff --git a/contrib/ast-db-manage/config/versions/a06d8f8462d9_add_t38_bind_udptl_to_media_address.py b/contrib/ast-db-manage/config/versions/a06d8f8462d9_add_t38_bind_udptl_to_media_address.py
new file mode 100644 (file)
index 0000000..2d9a58c
--- /dev/null
@@ -0,0 +1,29 @@
+"""add t38_bind_udptl_to_media_address
+
+Revision ID: a06d8f8462d9
+Revises: f56d79a9f337
+Create Date: 2021-09-24 10:03:01.320480
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'a06d8f8462d9'
+down_revision = 'f56d79a9f337'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+AST_BOOL_NAME = 'ast_bool_values'
+AST_BOOL_VALUES = [ '0', '1',
+                    'off', 'on',
+                    'false', 'true',
+                    'no', 'yes' ]
+
+def upgrade():
+    ast_bool_values = ENUM(*AST_BOOL_VALUES, name=AST_BOOL_NAME, create_type=False)
+    op.add_column('ps_endpoints', sa.Column('t38_bind_udptl_to_media_address', ast_bool_values))
+
+
+def downgrade():
+    op.drop_column('ps_endpoints', 't38_bind_udptl_to_media_address')
diff --git a/doc/CHANGES-staging/res_pjsip_t38_bind_fixes.txt b/doc/CHANGES-staging/res_pjsip_t38_bind_fixes.txt
new file mode 100644 (file)
index 0000000..d7bc8a1
--- /dev/null
@@ -0,0 +1,9 @@
+Subject: res_pjsip_t38
+
+In res_pjsip_sdp_rtp, the bind_rtp_to_media_address option and the
+fallback use of the transport's bind address solve problems sending
+media on systems that cannot send ipv4 packets on ipv6 sockets, and
+certain other situations. This change extends both of these behaviors
+to UDPTL sessions as well in res_pjsip_t38, to fix fax-specific
+problems on these systems, introducing a new option
+endpoint/t38_bind_udptl_to_media_address.
index 8c5b775bf5db7f2f15523bad6c14095b15951b9e..7b9dcbd51d0f742af344ec5509fe726ffd19f1f5 100644 (file)
@@ -760,6 +760,8 @@ struct ast_sip_t38_configuration {
        unsigned int nat;
        /*! Whether to use IPv6 for UDPTL or not */
        unsigned int ipv6;
+       /*! Bind the UDPTL instance to the media_address */
+       unsigned int bind_udptl_to_media_address;
 };
 
 /*!
index a375fe083b34112707a5e883f6545c444d9223af..2b30317738545bcf9c3e26f417e844c6193e73a0 100644 (file)
                                                When enabled the UDPTL stack will use IPv6.
                                        </para></description>
                                </configOption>
+                               <configOption name="t38_bind_udptl_to_media_address" default="no">
+                                       <synopsis>Bind the UDPTL instance to the media_adress</synopsis>
+                                       <description><para>
+                                               If media_address is specified, this option causes the UDPTL instance to be bound to
+                                               the specified ip address which causes the packets to be sent from that address.
+                                       </para></description>
+                               </configOption>
                                <configOption name="tone_zone">
                                        <synopsis>Set which country's indications to use for channels created for this endpoint.</synopsis>
                                </configOption>
                                <parameter name="T38UdptlIpv6">
                                        <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='t38_udptl_ipv6']/synopsis/node())"/></para>
                                </parameter>
+                               <parameter name="T38BindUdptlToMediaAddress">
+                                       <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='t38_bind_udptl_to_media_address']/synopsis/node())"/></para>
+                               </parameter>
                                <parameter name="ToneZone">
                                        <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='tone_zone']/synopsis/node())"/></para>
                                </parameter>
index 6defa7cb96a542d75ae9a13dad7b90afe52bd71c..c27b587076d79b3809b526331fbe77f3f3772596 100644 (file)
@@ -2077,6 +2077,7 @@ int ast_res_pjsip_initialize_configuration(void)
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, faxdetect_timeout));
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.nat));
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.ipv6));
+       ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_bind_udptl_to_media_address", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.bind_udptl_to_media_address));
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tone_zone", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, zone));
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "language", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, language));
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_on_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.onfeature));
index 5d7f68d09559ed8bbbd42a88b9e2b7ac7f86e94f..7df35d9b2ae0aa409ae2a934c25f4211d7b158b4 100644 (file)
@@ -255,11 +255,52 @@ static struct t38_state *t38_state_get_or_alloc(struct ast_sip_session *session)
 /*! \brief Initializes UDPTL support on a session, only done when actually needed */
 static int t38_initialize_session(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 {
+       struct ast_sockaddr temp_media_address;
+       struct ast_sockaddr *media_address = &address;
+
        if (session_media->udptl) {
                return 0;
        }
 
-       if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, &address))) {
+       if (session->endpoint->media.t38.bind_udptl_to_media_address && !ast_strlen_zero(session->endpoint->media.address)) {
+               if (ast_sockaddr_parse(&temp_media_address, session->endpoint->media.address, 0)) {
+                       ast_debug(5, "Endpoint %s: Binding UDPTL media to %s\n",
+                               ast_sorcery_object_get_id(session->endpoint),
+                               session->endpoint->media.address);
+                       media_address = &temp_media_address;
+               } else {
+                       ast_debug(5, "Endpoint %s: UDPTL media address invalid: %s\n",
+                               ast_sorcery_object_get_id(session->endpoint),
+                               session->endpoint->media.address);
+               }
+       } else {
+               struct ast_sip_transport *transport;
+
+               transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport",
+                               session->endpoint->transport);
+               if (transport) {
+                       struct ast_sip_transport_state *trans_state;
+
+                       trans_state = ast_sip_get_transport_state(ast_sorcery_object_get_id(transport));
+                       if (trans_state) {
+                               char hoststr[PJ_INET6_ADDRSTRLEN];
+
+                               pj_sockaddr_print(&trans_state->host, hoststr, sizeof(hoststr), 0);
+                               if (ast_sockaddr_parse(&temp_media_address, hoststr, 0)) {
+                                       ast_debug(5, "Transport %s bound to %s: Using it for UDPTL media.\n",
+                                               session->endpoint->transport, hoststr);
+                                       media_address = &temp_media_address;
+                               } else {
+                                       ast_debug(5, "Transport %s bound to %s: Invalid for UDPTL media.\n",
+                                               session->endpoint->transport, hoststr);
+                               }
+                               ao2_ref(trans_state, -1);
+                       }
+                       ao2_ref(transport, -1);
+               }
+       }
+
+       if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, media_address))) {
                return -1;
        }