diff --git a/CHANGES b/CHANGES index 8d5f5b388e1d6b8edbff5e794705f743ade54a08..6885c512adf1989e6341ba8d4d5f96a2c7168b03 100644 --- a/CHANGES +++ b/CHANGES @@ -234,6 +234,14 @@ Voicemail app_voicemail will be skipped. Use 'preload=app_voicemail.so' in modules.conf to force app_voicemail to be the voicemail provider. +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 ------------ ------------------------------------------------------------------------------ diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index 9302fb2619ed8c1c647377831139a15b5e8f2a42..c8d7cc90e9a451ddbeab12044d0f40690f3385bd 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -615,6 +615,9 @@ ;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 index 0000000000000000000000000000000000000000..e7c11da19259133cc38cd5b5eddca1d489078243 --- /dev/null +++ b/contrib/ast-db-manage/config/versions/26d7f3bf0fa5_add_bind_rtp_to_media_address_to_pjsip.py @@ -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') diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index df13af699454f3c9d3142404a662b4ea5423f933..0c82732833a343b98ee347336b1333f2de660975 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -575,6 +575,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; }; /*! diff --git a/res/res_pjsip.c b/res/res_pjsip.c index bf26fca8c6d012cb7d294ba0c83cfd71032b090b..90be734e678ae27a76bc8cdaef1b98ab284d9e4d 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -233,6 +233,14 @@ </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> diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 72f896ad0c4d1bd2beae19ee3aaf20ec9a788417..926bf3793cb1e3754abed954a1180b814594739d 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1847,6 +1847,7 @@ int ast_res_pjsip_initialize_configuration(void) 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); diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c index 1f2f21d7330602ad41d0198330a73a4c825c23f8..2a1f56ed4956bdf6aa6e41668d39d3a780881e97 100644 --- a/res/res_pjsip_sdp_rtp.c +++ b/res/res_pjsip_sdp_rtp.c @@ -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; }