]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
pjsip_sdp_rtp: Add option endpoint/bind_rtp_to_media_address 28/1928/5
authorGeorge Joseph <george.joseph@fairview5.com>
Thu, 7 Jan 2016 17:57:01 +0000 (10:57 -0700)
committerGeorge Joseph <george.joseph@fairview5.com>
Tue, 12 Jan 2016 00:39:55 +0000 (18:39 -0600)
On a system with multiple ip addresses in the same subnet, if a
transport is bound to a specific ip address and endpoint/media_address
 is set, the SIP/SDP will have the correct address in all fields but
the rtp stream MAY still originate from one of the other ip addresses,
most probably the "primary" ip address.  This happens because
 res_pjsip_sdp_rtp/create_rtp always calls ast_instance_new with
the "all" ip address (0.0.0.0 or ::).

The new option causes res_pjsip_sdp_rtp/create_rtp to call
ast_rtp_instance_new with the endpoint's media_address (if specified)
instead of the "all" address.  This causes the packets to originate from
the specified address.

ASTERISK-25632
ASTERISK-25637
Reported-by: Olivier Krief
Reported-by: Dan Journo
Change-Id: I3dfaa079e54ba7fb7c4fd1f5f7bd9509bbf8bd88

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

diff --git a/CHANGES b/CHANGES
index d9150a932601f1763580fc220655c88c6c65b1c6..4a6b85d1229c39da00754cdf6ceb930c1b3989af 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -46,6 +46,14 @@ Queue
  * Added field ReasonPause on QueueMemberStatus if set when paused, the reason
    the queue member was paused.
 
+res_pjsip_sdp_rtp
+------------------
+ * A new option (bind_rtp_to_media_address) has been added to endpoint which
+   will cause res_pjsip_sdp_rtp to actually bind the RTP instance to the
+   media_address as well as using it in the SDP.  If set, RTP packets will now
+   originate from the media address instead of the operating system's "primary"
+   ip address.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.6.0 to Asterisk 13.7.0 ------------
 ------------------------------------------------------------------------------
index 859635c983868761f855288a2d46bc988eeb85df..215245d8474a4893f851801d607fc1217be885b0 100644 (file)
 ;disallow=      ; Media Codec s to disallow (default: "")
 ;dtmf_mode=rfc4733      ; DTMF mode (default: "rfc4733")
 ;media_address=         ; IP address used in SDP for media handling (default: "")
+;bind_rtp_to_media_address=     ; Bind the RTP session to the media_address.
+                                ; This causes all RTP packets to be sent from
+                                ; the specified address. (default: "no")
 ;force_rport=yes        ; Force use of return port (default: "yes")
 ;ice_support=no ; Enable the ICE mechanism to help traverse NAT (default: "no")
 ;identify_by=username   ; Way s for Endpoint to be identified (default:
diff --git a/contrib/ast-db-manage/config/versions/26d7f3bf0fa5_add_bind_rtp_to_media_address_to_pjsip.py b/contrib/ast-db-manage/config/versions/26d7f3bf0fa5_add_bind_rtp_to_media_address_to_pjsip.py
new file mode 100644 (file)
index 0000000..e7c11da
--- /dev/null
@@ -0,0 +1,31 @@
+"""add bind_rtp_to_media_address to pjsip
+
+Revision ID: 26d7f3bf0fa5
+Revises: 2d078ec071b7
+Create Date: 2016-01-07 12:23:42.894400
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '26d7f3bf0fa5'
+down_revision = '2d078ec071b7'
+
+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('bind_rtp_to_media_address', yesno_values))
+
+
+def downgrade():
+    op.drop_column('ps_endpoints', 'bind_rtp_to_media_address')
index 6ca56bdcf38b1e74f3c340e5a741e4af02d3ef5f..8527f2441b741d1fb857539966918432bd7ceb6d 100644 (file)
@@ -571,6 +571,8 @@ struct ast_sip_endpoint_media_configuration {
        unsigned int cos_video;
        /*! Is g.726 packed in a non standard way */
        unsigned int g726_non_standard;
+       /*! Bind the RTP instance to the media_address */
+       unsigned int bind_rtp_to_media_address;
 };
 
 /*!
index 8e99c55d45e38f87125aee6b5e31d518f55ee85b..c263d80c3213d3ca95645b4fcd9c23620b8c64df 100644 (file)
                                        </para></note>
                                        </description>
                                </configOption>
+                               <configOption name="bind_rtp_to_media_address">
+                                       <synopsis>Bind the RTP instance to the media_address</synopsis>
+                                       <description><para>
+                                               If media_address is specified, this option causes the RTP instance to be bound to the
+                                               specified ip address which causes the packets to be sent from that address.
+                                       </para>
+                                       </description>
+                               </configOption>
                                <configOption name="force_rport" default="yes">
                                        <synopsis>Force use of return port</synopsis>
                                </configOption>
index 746a45742e84af95168be553f884c77e72eaf8ac..c7fc195d30fd606e51aa550e570a8f5294b98958 100644 (file)
@@ -1850,6 +1850,7 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
        ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, NULL, 0, 0);
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "aors", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, aors));
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_address", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.address));
+       ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bind_rtp_to_media_address", "no", OPT_BOOL_T, 1, STRFLDSET(struct ast_sip_endpoint, media.bind_rtp_to_media_address));
        ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "identify_by", "username", ident_handler, ident_to_str, NULL, 0, 0);
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "direct_media", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.direct_media.enabled));
        ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "direct_media_method", "invite", direct_media_method_handler, direct_media_method_to_str, NULL, 0, 0);
index f733ea4204403d746d7740b71e11b18db78d1c0e..0e1d7daf24be3d58b71a0655d2e0506a9993a8d6 100644 (file)
@@ -175,8 +175,15 @@ static int rtp_check_timeout(const void *data)
 static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media, unsigned int ipv6)
 {
        struct ast_rtp_engine_ice *ice;
+       struct ast_sockaddr temp_media_address;
+       struct ast_sockaddr *media_address =  ipv6 ? &address_ipv6 : &address_ipv4;
 
-       if (!(session_media->rtp = ast_rtp_instance_new(session->endpoint->media.rtp.engine, sched, ipv6 ? &address_ipv6 : &address_ipv4, NULL))) {
+       if (session->endpoint->media.bind_rtp_to_media_address && !ast_strlen_zero(session->endpoint->media.address)) {
+               ast_sockaddr_parse(&temp_media_address, session->endpoint->media.address, 0);
+               media_address = &temp_media_address;
+       }
+
+       if (!(session_media->rtp = ast_rtp_instance_new(session->endpoint->media.rtp.engine, sched, media_address, NULL))) {
                ast_log(LOG_ERROR, "Unable to create RTP instance using RTP engine '%s'\n", session->endpoint->media.rtp.engine);
                return -1;
        }