summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2016-10-25 05:29:08 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2016-10-25 05:29:08 -0500
commit2bd8af6d0bc3cc9e08457924f190a76ff8cbb0b7 (patch)
tree1b2420eaf4052f2f2eb2d46d74c66d207fa76745 /res
parent2203a50042d052956623caad46ccab538f0d10d3 (diff)
parentbb982480d815fb0d5059fbfa86682cd30846556c (diff)
Merge "pjsip: Support dual stack automatically." into 13
Diffstat (limited to 'res')
-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
6 files changed, 180 insertions, 72 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 039495d55..4927ea36a 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -4291,6 +4291,7 @@ static int unload_pjsip(void *data)
if (ast_pjsip_endpoint && serializer_pool[0]) {
ast_res_pjsip_cleanup_options_handling();
internal_sip_destroy_outbound_authentication();
+ ast_res_pjsip_cleanup_message_ip_updater();
ast_sip_destroy_distributor();
ast_res_pjsip_destroy_configuration();
ast_sip_destroy_system();
@@ -4460,6 +4461,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 04cd85408..11ad12c45 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.
*
@@ -248,6 +256,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 d52f6e406..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 029eb5d27..aaedde423 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -58,11 +58,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/*! \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;
@@ -172,11 +169,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);
@@ -888,7 +885,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;
}
@@ -1033,7 +1030,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 };
pjmedia_sdp_media *media;
const char *hostip = NULL;
@@ -1056,7 +1052,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;
}
@@ -1097,7 +1093,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);
@@ -1234,7 +1231,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;
}
@@ -1470,8 +1467,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 01bfefdd9..cf1211177 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -51,11 +51,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/*! \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 9b35301f9..6dc0d3abe 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -4972,6 +4972,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);
@@ -4980,6 +4989,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;