summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES13
-rw-r--r--configs/samples/pjsip.conf.sample9
-rwxr-xr-xcontrib/scripts/sip_to_pjsip/sip_to_pjsip.py2
-rw-r--r--res/res_pjsip.c7
-rw-r--r--res/res_pjsip/include/res_pjsip_private.h14
-rw-r--r--res/res_pjsip/pjsip_message_ip_updater.c (renamed from res/res_pjsip_multihomed.c)176
-rw-r--r--res/res_pjsip_sdp_rtp.c24
-rw-r--r--res/res_pjsip_t38.c13
-rw-r--r--res/res_rtp_asterisk.c18
9 files changed, 194 insertions, 82 deletions
diff --git a/CHANGES b/CHANGES
index 3cc1cd4f5..622973c48 100644
--- a/CHANGES
+++ b/CHANGES
@@ -35,6 +35,19 @@ res_pjsip
This limits the other side's codec choice to exactly what we prefer.
------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ----------
+------------------------------------------------------------------------------
+
+res_pjsip
+------------------
+ * Automatic dual stack support is now implemented. Depending on DNS resolution
+ and the transport used for sending a message the SIP signaling and SDP will
+ be updated with the correct IP address and protocol version. This means that
+ the rtp_ipv6 and t38_udptl_ipv6 options no longer have any effect. The
+ res_pjsip_multihomed module has also been moved into core res_pjsip to ensure
+ that messages are updated with the correct address information in all cases.
+
+------------------------------------------------------------------------------
--- Functionality changes from Asterisk 14.0.0 to Asterisk 14.1.0 ----------
------------------------------------------------------------------------------
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index c6293b6fb..3bb9dc5bb 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -112,9 +112,6 @@
; the prefix "external_" will only apply to communication with addresses
; outside the range set with "local_net=".
;
-; IPv6: For endpoints using IPv6, remember to set "rtp_ipv6=yes" so that the RTP
-; engine will also be able to bind to an IPv6 address.
-;
; You can have more than one of any type of transport, as long as it doesn't
; use the same resources (bind address, port, etc) as the others.
@@ -294,8 +291,6 @@
; If using the TLS enabled transport, you may want the "media_encryption=sdes"
; option to additionally enable SRTP, though they are not mutually inclusive.
;
-; Use the "rtp_ipv6=yes" option if you want to utilize RTP over an ipv6 transport.
-;
; If this endpoint were remote, and it was using a transport configured for NAT
; then you likely want to use "direct_media=no" to prevent audio issues.
@@ -315,7 +310,6 @@
;transport=transport-tls
;media_encryption=sdes
;transport=transport-udp-ipv6
-;rtp_ipv6=yes
;transport=transport-udp-nat
;direct_media=no
;
@@ -646,7 +640,6 @@
; must be provided (default: "")
;rewrite_contact=no ; Allow Contact header to be rewritten with the source
; IP address port (default: "no")
-;rtp_ipv6=no ; Allow use of IPv6 for RTP traffic (default: "no")
;rtp_symmetric=no ; Enforce that RTP must be symmetric (default: "no")
;send_diversion=yes ; Send the Diversion header conveying the diversion
; information to the called user agent (default: "yes")
@@ -699,8 +692,6 @@
; (default: "0")
;t38_udptl_nat=no ; Whether NAT support is enabled on UDPTL sessions
; (default: "no")
-;t38_udptl_ipv6=no ; Whether IPv6 is used for UDPTL Sessions (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/scripts/sip_to_pjsip/sip_to_pjsip.py b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
index 40e93547d..98a5e9546 100755
--- a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
+++ b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
@@ -374,7 +374,7 @@ def from_dtlsenable(key, val, section, pjsip, nmapped):
###############################################################################
# options in pjsip.conf on an endpoint that have no sip.conf equivalent:
-# type, rtp_ipv6, 100rel, trust_id_outbound, aggregate_mwi,
+# type, 100rel, trust_id_outbound, aggregate_mwi,
# connected_line_method
# known sip.conf peer keys that can be mapped to a pjsip.conf section/key
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index fa200be26..39c365aa1 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -4332,6 +4332,7 @@ static int unload_pjsip(void *data)
*/
if (ast_pjsip_endpoint && serializer_pool[0]) {
ast_res_pjsip_cleanup_options_handling();
+ ast_res_pjsip_cleanup_message_ip_updater();
ast_sip_destroy_distributor();
ast_res_pjsip_destroy_configuration();
ast_sip_destroy_system();
@@ -4499,6 +4500,12 @@ static int load_module(void)
}
ast_res_pjsip_init_options_handling(0);
+
+ if (ast_res_pjsip_init_message_ip_updater()) {
+ ast_log(LOG_ERROR, "Failed to initialize message IP updating. Aborting load\n");
+ goto error;
+ }
+
ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
AST_TEST_REGISTER(xml_sanitization_end_null);
diff --git a/res/res_pjsip/include/res_pjsip_private.h b/res/res_pjsip/include/res_pjsip_private.h
index b175b5e11..0bdb63325 100644
--- a/res/res_pjsip/include/res_pjsip_private.h
+++ b/res/res_pjsip/include/res_pjsip_private.h
@@ -184,6 +184,14 @@ void ast_sip_destroy_global_headers(void);
int ast_res_pjsip_init_options_handling(int reload);
/*!
+ * \internal Initialize message IP updating handling.
+ *
+ * \retval 0 on success
+ * \retval other on failure
+ */
+int ast_res_pjsip_init_message_ip_updater(void);
+
+/*!
* \internal
* \brief Initialize transport storage for contacts.
*
@@ -236,6 +244,12 @@ void ast_res_pjsip_cleanup_options_handling(void);
/*!
* \internal
+ * \brief Clean up res_pjsip message ip updating handling
+ */
+void ast_res_pjsip_cleanup_message_ip_updater(void);
+
+/*!
+ * \internal
* \brief Get threadpool options
*/
void sip_get_threadpool_options(struct ast_threadpool_options *threadpool_options);
diff --git a/res/res_pjsip_multihomed.c b/res/res_pjsip/pjsip_message_ip_updater.c
index 5deeb9247..7671ad0a7 100644
--- a/res/res_pjsip_multihomed.c
+++ b/res/res_pjsip/pjsip_message_ip_updater.c
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2014, Digium, Inc.
+ * Copyright (C) 2014-2016, Digium, Inc.
*
* Joshua Colp <jcolp@digium.com>
*
@@ -16,19 +16,78 @@
* at the top of the source tree.
*/
-/*** MODULEINFO
- <depend>pjproject</depend>
- <depend>res_pjsip</depend>
- <support_level>core</support_level>
- ***/
-
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include "asterisk/res_pjsip.h"
-#include "asterisk/module.h"
+#include "asterisk/res_pjsip_session.h"
+#include "include/res_pjsip_private.h"
+
+#define MOD_DATA_RESTRICTIONS "restrictions"
+
+static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata);
+
+/*! \brief Outgoing message modification restrictions */
+struct multihomed_message_restrictions {
+ /*! \brief Disallow modification of the From domain */
+ unsigned int disallow_from_domain_modification;
+};
+
+static pjsip_module multihomed_module = {
+ .name = { "Multihomed Routing", 18 },
+ .id = -1,
+ .priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 1,
+ .on_tx_request = multihomed_on_tx_message,
+ .on_tx_response = multihomed_on_tx_message,
+};
+
+/*! \brief Helper function to get (or allocate if not already present) restrictions on a message */
+static struct multihomed_message_restrictions *multihomed_get_restrictions(pjsip_tx_data *tdata)
+{
+ struct multihomed_message_restrictions *restrictions;
+
+ restrictions = ast_sip_mod_data_get(tdata->mod_data, multihomed_module.id, MOD_DATA_RESTRICTIONS);
+ if (restrictions) {
+ return restrictions;
+ }
+
+ restrictions = PJ_POOL_ALLOC_T(tdata->pool, struct multihomed_message_restrictions);
+ ast_sip_mod_data_set(tdata->pool, tdata->mod_data, multihomed_module.id, MOD_DATA_RESTRICTIONS, restrictions);
+
+ return restrictions;
+}
+
+/*! \brief Callback invoked on non-session outgoing messages */
+static void multihomed_outgoing_message(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata)
+{
+ struct multihomed_message_restrictions *restrictions = multihomed_get_restrictions(tdata);
+
+ restrictions->disallow_from_domain_modification = !ast_strlen_zero(endpoint->fromdomain);
+}
+
+/*! \brief PJSIP Supplement for tagging messages with restrictions */
+static struct ast_sip_supplement multihomed_supplement = {
+ .priority = AST_SIP_SUPPLEMENT_PRIORITY_FIRST,
+ .outgoing_request = multihomed_outgoing_message,
+ .outgoing_response = multihomed_outgoing_message,
+};
+
+/*! \brief Callback invoked on session outgoing messages */
+static void multihomed_session_outgoing_message(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
+{
+ struct multihomed_message_restrictions *restrictions = multihomed_get_restrictions(tdata);
+
+ restrictions->disallow_from_domain_modification = !ast_strlen_zero(session->endpoint->fromdomain);
+}
+
+/*! \brief PJSIP Session Supplement for tagging messages with restrictions */
+static struct ast_sip_session_supplement multihomed_session_supplement = {
+ .priority = 1,
+ .outgoing_request = multihomed_session_outgoing_message,
+ .outgoing_response = multihomed_session_outgoing_message,
+};
/*! \brief Helper function which returns a UDP transport bound to the given address and port */
static pjsip_transport *multihomed_get_udp_transport(pj_str_t *address, int port)
@@ -59,6 +118,21 @@ static pjsip_transport *multihomed_get_udp_transport(pj_str_t *address, int port
return sip_transport;
}
+/*! \brief Helper function which determines if a transport is bound to any */
+static int multihomed_bound_any(pjsip_transport *transport)
+{
+ pj_uint32_t loop6[4] = {0, 0, 0, 0};
+
+ if ((transport->local_addr.addr.sa_family == pj_AF_INET() &&
+ transport->local_addr.ipv4.sin_addr.s_addr == PJ_INADDR_ANY) ||
+ (transport->local_addr.addr.sa_family == pj_AF_INET6() &&
+ !pj_memcmp(&transport->local_addr.ipv6.sin6_addr, loop6, sizeof(loop6)))) {
+ return 1;
+ }
+
+ return 0;
+}
+
/*! \brief Helper function which determines if the address within SDP should be rewritten */
static int multihomed_rewrite_sdp(struct pjmedia_sdp_session *sdp)
{
@@ -77,26 +151,13 @@ static int multihomed_rewrite_sdp(struct pjmedia_sdp_session *sdp)
return 0;
}
-/*! \brief Helper function which determines if a transport is bound to any */
-static int multihomed_bound_any(pjsip_transport *transport)
-{
- pj_uint32_t loop6[4] = {0, 0, 0, 0};
-
- if ((transport->local_addr.addr.sa_family == pj_AF_INET() &&
- transport->local_addr.ipv4.sin_addr.s_addr == PJ_INADDR_ANY) ||
- (transport->local_addr.addr.sa_family == pj_AF_INET6() &&
- !pj_memcmp(&transport->local_addr.ipv6.sin6_addr, loop6, sizeof(loop6)))) {
- return 1;
- }
-
- return 0;
-}
-
static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
{
+ struct multihomed_message_restrictions *restrictions = ast_sip_mod_data_get(tdata->mod_data, multihomed_module.id, MOD_DATA_RESTRICTIONS);
pjsip_tpmgr_fla2_param prm;
pjsip_cseq_hdr *cseq;
pjsip_via_hdr *via;
+ pjsip_fromto_hdr *from;
/* Use the destination information to determine what local interface this message will go out on */
pjsip_tpmgr_fla2_param_default(&prm);
@@ -153,6 +214,13 @@ static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
ast_debug(4, "Re-wrote Contact URI host/port to %.*s:%d\n",
(int)pj_strlen(&uri->host), pj_strbuf(&uri->host), uri->port);
+ if (tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP ||
+ tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP6) {
+ uri->transport_param.slen = 0;
+ } else {
+ pj_strdup2(tdata->pool, &uri->transport_param, pjsip_transport_get_type_name(tdata->tp_info.transport->key.type));
+ }
+
pjsip_tx_data_invalidate_msg(tdata);
}
}
@@ -164,17 +232,38 @@ static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
pjsip_tx_data_invalidate_msg(tdata);
}
+ if (tdata->msg->type == PJSIP_REQUEST_MSG && (from = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_FROM, NULL)) &&
+ (restrictions && !restrictions->disallow_from_domain_modification)) {
+ pjsip_name_addr *id_name_addr = (pjsip_name_addr *)from->uri;
+ pjsip_sip_uri *uri = pjsip_uri_get_uri(id_name_addr);
+ pj_sockaddr ip;
+
+ if (pj_strcmp2(&uri->host, "localhost") && pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &uri->host, &ip) == PJ_SUCCESS) {
+ pj_strassign(&uri->host, &prm.ret_addr);
+ pjsip_tx_data_invalidate_msg(tdata);
+ }
+ }
+
/* Update the SDP if it is present */
if (tdata->msg->body && ast_sip_is_content_type(&tdata->msg->body->content_type, "application", "sdp") &&
multihomed_rewrite_sdp(tdata->msg->body->data)) {
struct pjmedia_sdp_session *sdp = tdata->msg->body->data;
+ static const pj_str_t STR_IP4 = { "IP4", 3 };
+ static const pj_str_t STR_IP6 = { "IP6", 3 };
+ pj_str_t STR_IP;
int stream;
+ STR_IP = tdata->tp_info.transport->key.type & PJSIP_TRANSPORT_IPV6 ? STR_IP6 : STR_IP4;
+
+ pj_strassign(&sdp->origin.addr, &prm.ret_addr);
+ sdp->origin.addr_type = STR_IP;
pj_strassign(&sdp->conn->addr, &prm.ret_addr);
+ sdp->conn->addr_type = STR_IP;
for (stream = 0; stream < sdp->media_count; ++stream) {
if (sdp->media[stream]->conn) {
pj_strassign(&sdp->media[stream]->conn->addr, &prm.ret_addr);
+ sdp->media[stream]->conn->addr_type = STR_IP;
}
}
@@ -184,42 +273,31 @@ static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
return PJ_SUCCESS;
}
-static pjsip_module multihomed_module = {
- .name = { "Multihomed Routing", 18 },
- .id = -1,
- .priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 1,
- .on_tx_request = multihomed_on_tx_message,
- .on_tx_response = multihomed_on_tx_message,
-};
-
-static int unload_module(void)
+void ast_res_pjsip_cleanup_message_ip_updater(void)
{
ast_sip_unregister_service(&multihomed_module);
- return 0;
+ ast_sip_unregister_supplement(&multihomed_supplement);
+ ast_sip_session_unregister_supplement(&multihomed_session_supplement);
}
-static int load_module(void)
+int ast_res_pjsip_init_message_ip_updater(void)
{
- char hostname[MAXHOSTNAMELEN] = "";
-
- CHECK_PJSIP_MODULE_LOADED();
+ if (ast_sip_session_register_supplement(&multihomed_session_supplement)) {
+ ast_log(LOG_ERROR, "Could not register multihomed session supplement for outgoing requests\n");
+ return -1;
+ }
- if (!gethostname(hostname, sizeof(hostname) - 1)) {
- ast_verb(2, "Performing DNS resolution of local hostname '%s' to get local IPv4 and IPv6 address\n",
- hostname);
+ if (ast_sip_register_supplement(&multihomed_supplement)) {
+ ast_log(LOG_ERROR, "Could not register multihomed supplement for outgoing requests\n");
+ ast_res_pjsip_cleanup_message_ip_updater();
+ return -1;
}
if (ast_sip_register_service(&multihomed_module)) {
ast_log(LOG_ERROR, "Could not register multihomed module for incoming and outgoing requests\n");
- return AST_MODULE_LOAD_FAILURE;
+ ast_res_pjsip_cleanup_message_ip_updater();
+ return -1;
}
- return AST_MODULE_LOAD_SUCCESS;
+ return 0;
}
-
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Multihomed Routing Support",
- .support_level = AST_MODULE_SUPPORT_CORE,
- .load = load_module,
- .unload = unload_module,
- .load_pri = AST_MODPRI_APP_DEPEND,
-);
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index 68d5fdb56..a69aa1a74 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -59,11 +59,8 @@ ASTERISK_REGISTER_FILE()
/*! \brief Scheduler for RTCP purposes */
static struct ast_sched_context *sched;
-/*! \brief Address for IPv4 RTP */
-static struct ast_sockaddr address_ipv4;
-
-/*! \brief Address for IPv6 RTP */
-static struct ast_sockaddr address_ipv6;
+/*! \brief Address for RTP */
+static struct ast_sockaddr address_rtp;
static const char STR_AUDIO[] = "audio";
static const int FD_AUDIO = 0;
@@ -173,11 +170,11 @@ static int rtp_check_timeout(const void *data)
}
/*! \brief Internal function which creates an RTP instance */
-static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media, unsigned int ipv6)
+static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
{
struct ast_rtp_engine_ice *ice;
struct ast_sockaddr temp_media_address;
- struct ast_sockaddr *media_address = ipv6 ? &address_ipv6 : &address_ipv4;
+ struct ast_sockaddr *media_address = &address_rtp;
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);
@@ -903,7 +900,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
}
/* Using the connection information create an appropriate RTP instance */
- if (!session_media->rtp && create_rtp(session, session_media, ast_sockaddr_is_ipv6(addrs))) {
+ if (!session_media->rtp && create_rtp(session, session_media)) {
return -1;
}
@@ -1055,7 +1052,6 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
pj_pool_t *pool = session->inv_session->pool_prov;
static const pj_str_t STR_IN = { "IN", 2 };
static const pj_str_t STR_IP4 = { "IP4", 3};
- static const pj_str_t STR_IP6 = { "IP6", 3};
static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
static const pj_str_t STR_SENDONLY = { "sendonly", 8 };
pjmedia_sdp_media *media;
@@ -1079,7 +1075,7 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
(!use_override_prefs && !ast_format_cap_has_type(session->endpoint->media.codecs, media_type))) {
/* If no type formats are configured don't add a stream */
return 0;
- } else if (!session_media->rtp && create_rtp(session, session_media, session->endpoint->media.rtp.ipv6)) {
+ } else if (!session_media->rtp && create_rtp(session, session_media)) {
return -1;
}
@@ -1120,7 +1116,8 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
}
media->conn->net_type = STR_IN;
- media->conn->addr_type = session->endpoint->media.rtp.ipv6 ? STR_IP6 : STR_IP4;
+ /* Connection information will be updated by the multihomed module */
+ media->conn->addr_type = STR_IP4;
pj_strdup2(pool, &media->conn->addr, hostip);
ast_rtp_instance_get_local_address(session_media->rtp, &addr);
media->desc.port = direct_media_enabled ? ast_sockaddr_port(&session_media->direct_media_addr) : (pj_uint16_t) ast_sockaddr_port(&addr);
@@ -1257,7 +1254,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
}
/* Create an RTP instance if need be */
- if (!session_media->rtp && create_rtp(session, session_media, session->endpoint->media.rtp.ipv6)) {
+ if (!session_media->rtp && create_rtp(session, session_media)) {
return -1;
}
@@ -1493,8 +1490,7 @@ static int load_module(void)
{
CHECK_PJSIP_SESSION_MODULE_LOADED();
- ast_sockaddr_parse(&address_ipv4, "0.0.0.0", 0);
- ast_sockaddr_parse(&address_ipv6, "::", 0);
+ ast_sockaddr_parse(&address_rtp, "::", 0);
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
index 150336a08..b052cc428 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -51,11 +51,8 @@ ASTERISK_REGISTER_FILE()
/*! \brief The number of seconds after receiving a T.38 re-invite before automatically rejecting it */
#define T38_AUTOMATIC_REJECTION_SECONDS 5
-/*! \brief Address for IPv4 UDPTL */
-static struct ast_sockaddr address_ipv4;
-
-/*! \brief Address for IPv6 UDPTL */
-static struct ast_sockaddr address_ipv6;
+/*! \brief Address for UDPTL */
+static struct ast_sockaddr address;
/*! \brief T.38 state information */
struct t38_state {
@@ -259,8 +256,7 @@ static int t38_initialize_session(struct ast_sip_session *session, struct ast_si
return 0;
}
- if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0,
- session->endpoint->media.t38.ipv6 ? &address_ipv6 : &address_ipv4))) {
+ if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, &address))) {
return -1;
}
@@ -922,8 +918,7 @@ static int load_module(void)
{
CHECK_PJSIP_SESSION_MODULE_LOADED();
- ast_sockaddr_parse(&address_ipv4, "0.0.0.0", 0);
- ast_sockaddr_parse(&address_ipv6, "::", 0);
+ ast_sockaddr_parse(&address, "::", 0);
if (ast_sip_session_register_supplement(&t38_supplement)) {
ast_log(LOG_ERROR, "Unable to register T.38 session supplement\n");
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 4bf625260..cdf0c560d 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -4971,6 +4971,15 @@ static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp)
static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+ struct ast_sockaddr local, us;
+
+ if (!ast_sockaddr_isnull(addr)) {
+ /* Update the local RTP address with what is being used */
+ ast_ouraddrfor(addr, &us);
+ ast_rtp_instance_get_local_address(instance, &local);
+ ast_sockaddr_set_port(&us, ast_sockaddr_port(&local));
+ ast_rtp_instance_set_local_address(instance, &us);
+ }
if (rtp->rtcp) {
ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
@@ -4979,6 +4988,15 @@ static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct
ast_sockaddr_set_port(&rtp->rtcp->them,
ast_sockaddr_port(addr) + 1);
}
+
+ if (!ast_sockaddr_isnull(addr)) {
+ /* Update the local RTCP address with what is being used */
+ ast_sockaddr_set_port(&us, ast_sockaddr_port(&local) + 1);
+ ast_sockaddr_copy(&rtp->rtcp->us, &us);
+
+ ast_free(rtp->rtcp->local_addr_str);
+ rtp->rtcp->local_addr_str = ast_strdup(ast_sockaddr_stringify(&us));
+ }
}
rtp->rxseqno = 0;