diff options
-rw-r--r-- | CHANGES | 22 | ||||
-rw-r--r-- | channels/pjsip/dialplan_functions.c | 18 | ||||
-rw-r--r-- | configs/samples/hep.conf.sample | 10 | ||||
-rw-r--r-- | contrib/ast-db-manage/config/versions/465e70e8c337_add_match_header_attribute_to_identify.py | 21 | ||||
-rw-r--r-- | funcs/func_devstate.c | 2 | ||||
-rw-r--r-- | main/stasis_cache.c | 2 | ||||
-rw-r--r-- | menuselect/menuselect.c | 8 | ||||
-rw-r--r-- | menuselect/menuselect.h | 3 | ||||
-rw-r--r-- | res/res_pjsip.c | 22 | ||||
-rw-r--r-- | res/res_pjsip_endpoint_identifier_ip.c | 96 | ||||
-rw-r--r-- | res/res_pjsip_outbound_registration.c | 18 | ||||
-rw-r--r-- | res/res_pjsip_transport_websocket.c | 30 | ||||
-rw-r--r-- | third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch | 62 |
13 files changed, 265 insertions, 49 deletions
@@ -12,6 +12,14 @@ --- Functionality changes from Asterisk 13.14.0 to Asterisk 13.15.0 ---------- ------------------------------------------------------------------------------ +AMI +------------------ + * The 'PJSIPShowEndpoint' command's respone event of 'IdentifyDetail' now + contains a new optional parameter, 'MatchHeader', mapping to the new + configuration option 'match_header' for the corresponding 'identify' object. + It should be noted that since 'match_header' takes in a key: value pair, the + event parameter will contain a ':' as well. + app_record ------------------ * Added new 'u' option to Record() application which prevents Asterisk from @@ -41,6 +49,20 @@ res_pjsip_transport_websocket when Asterisk attempts to send SIP requests to do something like initiate call hangup. +res_pjsip_endpoint_identifier_ip +------------------ + * A new option has been added to the 'identify' configuration object, + 'match_header'. The 'match_header' attribute should contain a SIP + header: value pair that, When set, will cause inbound requests that contain + the matching SIP header/value pair to be associated with the corresponding + endpoint. This option is cumulative with the 'match' option, so that if + either option matches the request, the request is associated with the + endpoint. + + In a future release, this module will be renamed to something more + appropriate, as it now matches inbound requests on more than just IP + address. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 13.13.0 to Asterisk 13.14.0 ---------- ------------------------------------------------------------------------------ diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c index 719a0747c..652a6b7f3 100644 --- a/channels/pjsip/dialplan_functions.c +++ b/channels/pjsip/dialplan_functions.c @@ -737,17 +737,27 @@ static int read_pjsip(void *data) struct pjsip_func_args *func_args = data; if (!strcmp(func_args->param, "rtp")) { + if (!func_args->session->channel) { + func_args->ret = -1; + return 0; + } func_args->ret = channel_read_rtp(func_args->session->channel, func_args->type, func_args->field, func_args->buf, func_args->len); } else if (!strcmp(func_args->param, "rtcp")) { + if (!func_args->session->channel) { + func_args->ret = -1; + return 0; + } func_args->ret = channel_read_rtcp(func_args->session->channel, func_args->type, func_args->field, func_args->buf, func_args->len); } else if (!strcmp(func_args->param, "endpoint")) { if (!func_args->session->endpoint) { - ast_log(AST_LOG_WARNING, "Channel %s has no endpoint!\n", ast_channel_name(func_args->session->channel)); - return -1; + ast_log(AST_LOG_WARNING, "Channel %s has no endpoint!\n", func_args->session->channel ? + ast_channel_name(func_args->session->channel) : "<unknown>"); + func_args->ret = -1; + return 0; } snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(func_args->session->endpoint)); } else if (!strcmp(func_args->param, "contact")) { @@ -761,6 +771,10 @@ static int read_pjsip(void *data) } snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(func_args->session->aor)); } else if (!strcmp(func_args->param, "pjsip")) { + if (!func_args->session->channel) { + func_args->ret = -1; + return 0; + } func_args->ret = channel_read_pjsip(func_args->session->channel, func_args->type, func_args->field, func_args->buf, func_args->len); diff --git a/configs/samples/hep.conf.sample b/configs/samples/hep.conf.sample index e1cd52ebb..3d1e74139 100644 --- a/configs/samples/hep.conf.sample +++ b/configs/samples/hep.conf.sample @@ -2,6 +2,15 @@ ; res_hep Module configuration for Asterisk ; +; +; Note that this configuration file is consumed by res_hep, which is responsible +; for the HEPv3 protocol manipulation and managing the connection to the Homer +; capture server. Additional modules provide specific messages to be sent to +; the Homer server: +; - res_hep_pjsip: Send SIP messages transmitted/received by the PJSIP stack +; - res_hep_rtcp: Send RTCP information (all channels) +; + ; All settings are currently set in the general section. [general] enabled = no ; Enable/disable forwarding of packets to a @@ -17,4 +26,3 @@ uuid_type = call-id ; Specify the preferred source for the Homer ; correlation UUID. Valid options are: ; - 'call-id' for the PJSIP SIP Call-ID ; - 'channel' for the Asterisk channel name - diff --git a/contrib/ast-db-manage/config/versions/465e70e8c337_add_match_header_attribute_to_identify.py b/contrib/ast-db-manage/config/versions/465e70e8c337_add_match_header_attribute_to_identify.py new file mode 100644 index 000000000..343b5cba9 --- /dev/null +++ b/contrib/ast-db-manage/config/versions/465e70e8c337_add_match_header_attribute_to_identify.py @@ -0,0 +1,21 @@ +"""Add match_header attribute to identify + +Revision ID: 465e70e8c337 +Revises: 28ab27a7826d +Create Date: 2017-03-14 08:13:53.986681 + +""" + +# revision identifiers, used by Alembic. +revision = '465e70e8c337' +down_revision = '28ab27a7826d' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.add_column('ps_endpoint_id_ips', sa.Column('match_header', sa.String(255))) + +def downgrade(): + op.drop_column('ps_endpoint_id_ips', 'match_header') diff --git a/funcs/func_devstate.c b/funcs/func_devstate.c index 88a5c5c71..21759bc33 100644 --- a/funcs/func_devstate.c +++ b/funcs/func_devstate.c @@ -341,7 +341,7 @@ static int load_module(void) if (dev_name <= (const char *) 1) continue; ast_devstate_changed(ast_devstate_val(db_entry->data), - AST_DEVSTATE_CACHABLE, "Custom:%s\n", dev_name); + AST_DEVSTATE_CACHABLE, "Custom:%s", dev_name); } ast_db_freetree(db_tree); db_tree = NULL; diff --git a/main/stasis_cache.c b/main/stasis_cache.c index 9129c0064..b0973b984 100644 --- a/main/stasis_cache.c +++ b/main/stasis_cache.c @@ -842,7 +842,7 @@ static void caching_topic_exec(void *data, struct stasis_subscription *sub, } ao2_cleanup(update); } else { - ast_log(LOG_ERROR, + ast_debug(1, "Attempting to remove an item from the %s cache that isn't there: %s %s\n", stasis_topic_name(caching_topic->topic), stasis_message_type_name(msg_type), msg_id); diff --git a/menuselect/menuselect.c b/menuselect/menuselect.c index da972d8b1..689cebf62 100644 --- a/menuselect/menuselect.c +++ b/menuselect/menuselect.c @@ -238,6 +238,10 @@ static enum support_level_values string_to_support_level(const char *support_lev return SUPPORT_EXTERNAL; } + if (!strcasecmp(support_level, "option")) { + return SUPPORT_OPTION; + } + return SUPPORT_UNSPECIFIED; } @@ -253,6 +257,8 @@ static const char *support_level_to_string(enum support_level_values support_lev return "Deprecated"; case SUPPORT_EXTERNAL: return "External"; + case SUPPORT_OPTION: + return "Module Options"; default: return "Unspecified"; } @@ -461,7 +467,7 @@ static int process_xml_member_node(xmlNode *node, struct category *cat) process_process_xml_category_child_node(cur, mem); } - if (!cat->positive_output) { + if (!cat->positive_output && strcasecmp(mem->support_level, "option")) { mem->enabled = 1; if (!mem->defaultenabled || strcasecmp(mem->defaultenabled, "no")) { mem->was_enabled = 1; diff --git a/menuselect/menuselect.h b/menuselect/menuselect.h index bf2bf4c4f..78ae8eff6 100644 --- a/menuselect/menuselect.h +++ b/menuselect/menuselect.h @@ -108,7 +108,8 @@ enum support_level_values { SUPPORT_DEPRECATED = 2, SUPPORT_UNSPECIFIED = 3, SUPPORT_EXTERNAL = 4, - SUPPORT_COUNT = 5, /* Keep this item at the end of the list. Tracks total number of support levels. */ + SUPPORT_OPTION = 5, + SUPPORT_COUNT = 6, /* Keep this item at the end of the list. Tracks total number of support levels. */ }; AST_LIST_HEAD_NOLOCK(support_level_bucket, member); diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 54a0a5f39..347658f9c 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -2755,7 +2755,7 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u pj_str_t tmp, local_addr; pjsip_uri *uri; pjsip_sip_uri *sip_uri; - pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED; + pjsip_transport_type_e type; int local_port; char default_user[PJSIP_MAX_URL_SIZE]; @@ -2775,21 +2775,21 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u sip_uri = pjsip_uri_get_uri(uri); /* Determine the transport type to use */ + type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) { - type = PJSIP_TRANSPORT_TLS; + if (type == PJSIP_TRANSPORT_UNSPECIFIED + || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) { + type = PJSIP_TRANSPORT_TLS; + } } else if (!sip_uri->transport_param.slen) { type = PJSIP_TRANSPORT_UDP; - } else { - type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); - } - - if (type == PJSIP_TRANSPORT_UNSPECIFIED) { + } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) { return -1; } /* If the host is IPv6 turn the transport into an IPv6 version */ - if (pj_strchr(&sip_uri->host, ':') && type < PJSIP_TRANSPORT_START_OTHER) { - type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6); + if (pj_strchr(&sip_uri->host, ':')) { + type |= PJSIP_TRANSPORT_IPV6; } if (!ast_strlen_zero(domain)) { @@ -2813,8 +2813,8 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u } /* If IPv6 was specified in the transport, set the proper type */ - if (pj_strchr(&local_addr, ':') && type < PJSIP_TRANSPORT_START_OTHER) { - type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6); + if (pj_strchr(&local_addr, ':')) { + type |= PJSIP_TRANSPORT_IPV6; } from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c index 6fc724a1e..1bd7e892d 100644 --- a/res/res_pjsip_endpoint_identifier_ip.c +++ b/res/res_pjsip_endpoint_identifier_ip.c @@ -35,20 +35,33 @@ /*** DOCUMENTATION <configInfo name="res_pjsip_endpoint_identifier_ip" language="en_US"> - <synopsis>Module that identifies endpoints via source IP address</synopsis> + <synopsis>Module that identifies endpoints</synopsis> <configFile name="pjsip.conf"> <configObject name="identify"> - <synopsis>Identifies endpoints via source IP address</synopsis> + <synopsis>Identifies endpoints via some criteria.</synopsis> + <description> + <para>This module provides alternatives to matching inbound requests to + a configured endpoint. At least one of the matching mechanisms + must be provided, or the object configuration will be invalid.</para> + <para>If multiple criteria are provided, an inbound request will + be matched if it matches <emphasis>any</emphasis> of the criteria.</para> + <para>The matching mechanisms are provided by the following + configuration options:</para> + <enumlist> + <enum name="match"><para>Match by source IP address.</para></enum> + <enum name="match_header"><para>Match by SIP header.</para></enum> + </enumlist> + </description> <configOption name="endpoint"> <synopsis>Name of Endpoint</synopsis> </configOption> <configOption name="match"> - <synopsis>IP addresses or networks to match against</synopsis> + <synopsis>IP addresses or networks to match against.</synopsis> <description><para> The value is a comma-delimited list of IP addresses. IP addresses may have a subnet mask appended. The subnet mask may be written in either CIDR or dot-decimal notation. Separate the IP address and subnet - mask with a slash ('/') + mask with a slash ('/'). </para></description> </configOption> <configOption name="srv_lookups" default="yes"> @@ -57,7 +70,15 @@ perform SRV lookups for _sip._udp, _sip._tcp, and _sips._tcp of the given hostnames to determine additional addresses that traffic may originate from. </para></description> - </configOption> + </configOption> + <configOption name="match_header"> + <synopsis>Header/value pair to match against.</synopsis> + <description><para>A SIP header who value is used to match against. SIP + requests containing the header, along with the specified value, will be + mapped to the specified endpoint. The header must be specified with a + <literal>:</literal>, as in <literal>match_header = SIPHeader: value</literal>. + </para></description> + </configOption> <configOption name="type"> <synopsis>Must be of type 'identify'.</synopsis> </configOption> @@ -77,6 +98,8 @@ struct ip_identify_match { AST_DECLARE_STRING_FIELDS( /*! The name of the endpoint */ AST_STRING_FIELD(endpoint_name); + /*! If matching by header, the header/value to match against */ + AST_STRING_FIELD(match_header); ); /*! \brief Networks or addresses that should match this */ struct ast_ha *matches; @@ -109,7 +132,48 @@ static void *ip_identify_alloc(const char *name) return identify; } -/*! \brief Comparator function for a matching object */ +/*! \brief Comparator function for matching an object by header */ +static int header_identify_match_check(void *obj, void *arg, int flags) +{ + struct ip_identify_match *identify = obj; + struct pjsip_rx_data *rdata = arg; + pjsip_generic_string_hdr *header; + pj_str_t pj_header_name; + pj_str_t pj_header_value; + char *c_header = ast_strdupa(identify->match_header); + char *c_value; + + c_value = strchr(c_header, ':'); + if (!c_value) { + ast_log(LOG_WARNING, "Identify '%s' has invalid header_match: No ':' separator found!\n", + ast_sorcery_object_get_id(identify)); + return 0; + } + *c_value = '\0'; + c_value++; + c_value = ast_strip(c_value); + + pj_header_name = pj_str(c_header); + header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &pj_header_name, NULL); + if (!header) { + ast_debug(3, "SIP message does not contain header '%s'\n", c_header); + return 0; + } + + pj_header_value = pj_str(c_value); + if (pj_strcmp(&pj_header_value, &header->hvalue)) { + ast_debug(3, "SIP message contains header '%s' but value '%.*s' does not match value '%s' for endpoint '%s'\n", + c_header, + (int) pj_strlen(&header->hvalue), pj_strbuf(&header->hvalue), + c_value, + identify->endpoint_name); + return 0; + } + + return CMP_MATCH | CMP_STOP; +} + +/*! \brief Comparator function for matching an object by IP address */ static int ip_identify_match_check(void *obj, void *arg, int flags) { struct ip_identify_match *identify = obj; @@ -147,10 +211,14 @@ static struct ast_sip_endpoint *ip_identify(pjsip_rx_data *rdata) ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID); ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port); - if (!(match = ao2_callback(candidates, 0, ip_identify_match_check, &addr))) { - ast_debug(3, "'%s' did not match any identify section rules\n", + match = ao2_callback(candidates, 0, ip_identify_match_check, &addr); + if (!match) { + ast_debug(3, "Identify checks by IP address failed to find match: '%s' did not match any identify section rules\n", ast_sockaddr_stringify(&addr)); - return NULL; + match = ao2_callback(candidates, 0, header_identify_match_check, rdata); + if (!match) { + return NULL; + } } endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", match->endpoint_name); @@ -495,7 +563,7 @@ static int cli_print_header(void *obj, void *arg, int flags) filler = CLI_LAST_TABSTOP - indent - 24; ast_str_append(&context->output_buffer, 0, - "%*s: <ip/cidr%*.*s>\n", + "%*s: <criteria%*.*s>\n", indent, "Match", filler, filler, CLI_HEADER_FILLER); context->indent_level--; @@ -532,6 +600,13 @@ static int cli_print_body(void *obj, void *arg, int flags) addr, ast_sockaddr_cidr_bits(&match->netmask)); } + if (!ast_strlen_zero(ident->match_header)) { + ast_str_append(&context->output_buffer, 0, "%*s: %s\n", + indent, + "Match", + ident->match_header); + } + context->indent_level--; if (context->indent_level == 0) { @@ -592,6 +667,7 @@ static int load_module(void) ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "type", "", OPT_NOOP_T, 0, 0); ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, endpoint_name)); ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "identify", "match", "", ip_identify_match_handler, match_to_str, match_to_var_list, 0, 0); + ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "match_header", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, match_header)); ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "srv_lookups", "yes", OPT_BOOL_T, 1, FLDSET(struct ip_identify_match, srv_lookups)); ast_sorcery_load_object(ast_sip_get_sorcery(), "identify"); diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c index 7a0b60ac8..ee1894ffb 100644 --- a/res/res_pjsip_outbound_registration.c +++ b/res/res_pjsip_outbound_registration.c @@ -1087,7 +1087,7 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c pj_str_t tmp, local_addr; pjsip_uri *uri; pjsip_sip_uri *sip_uri; - pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED; + pjsip_transport_type_e type; int local_port; pj_strdup_with_null(pool, &tmp, target); @@ -1099,20 +1099,20 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c sip_uri = pjsip_uri_get_uri(uri); + type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) { - type = PJSIP_TRANSPORT_TLS; + if (type == PJSIP_TRANSPORT_UNSPECIFIED + || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) { + type = PJSIP_TRANSPORT_TLS; + } } else if (!sip_uri->transport_param.slen) { type = PJSIP_TRANSPORT_UDP; - } else { - type = pjsip_transport_get_type_from_name(&sip_uri->transport_param); - } - - if (type == PJSIP_TRANSPORT_UNSPECIFIED) { + } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) { return -1; } if (pj_strchr(&sip_uri->host, ':')) { - type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6); + type |= PJSIP_TRANSPORT_IPV6; } if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), @@ -1121,7 +1121,7 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c } if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) { - type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6); + type |= PJSIP_TRANSPORT_IPV6; } contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c index ff8e346f4..1b9d616de 100644 --- a/res/res_pjsip_transport_websocket.c +++ b/res/res_pjsip_transport_websocket.c @@ -39,6 +39,7 @@ #include "asterisk/taskprocessor.h" static int transport_type_wss; +static int transport_type_wss_ipv6; /*! * \brief Wrapper for pjsip_transport, for storing the WebSocket session @@ -198,15 +199,20 @@ static int transport_create(void *data) newtransport->transport.type_name, ws_addr_str); pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.key.rem_addr); - newtransport->transport.key.rem_addr.addr.sa_family = pj_AF_INET(); - newtransport->transport.key.type = transport_type_wss; + if (newtransport->transport.key.rem_addr.addr.sa_family == pj_AF_INET6()) { + newtransport->transport.key.type = transport_type_wss_ipv6; + newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN); + pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET6_ADDRSTRLEN, 0); + } else { + newtransport->transport.key.type = transport_type_wss; + newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET_ADDRSTRLEN); + pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET_ADDRSTRLEN, 0); + } newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr); pj_sockaddr_cp(&newtransport->transport.local_addr, &newtransport->transport.key.rem_addr); - newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, newtransport->transport.addr_len+4); - pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, newtransport->transport.addr_len+4, 0); newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr); newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr); @@ -271,8 +277,6 @@ static int transport_read(void *data) rdata->pkt_info.zero = 0; pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ast_sockaddr_stringify(ast_websocket_remote_address(session))), &rdata->pkt_info.src_addr); - rdata->pkt_info.src_addr.addr.sa_family = pj_AF_INET(); - rdata->pkt_info.src_addr_len = sizeof(rdata->pkt_info.src_addr); pj_ansi_strcpy(rdata->pkt_info.src_name, ast_sockaddr_stringify_host(ast_websocket_remote_address(session))); @@ -395,7 +399,7 @@ static pj_bool_t websocket_on_rx_msg(pjsip_rx_data *rdata) long type = rdata->tp_info.transport->key.type; - if (type != (long) transport_type_wss) { + if (type != (long) transport_type_wss && type != (long) transport_type_wss_ipv6) { return PJ_FALSE; } @@ -451,15 +455,17 @@ static int load_module(void) CHECK_PJSIP_MODULE_LOADED(); /* - * We only need one transport type defined. Firefox and Chrome - * do not support anything other than secure websockets anymore. + * We only need one transport type name (ws) defined. Firefox + * and Chrome do not support anything other than secure websockets + * anymore. * * Also we really cannot have two transports with the same name - * because it would be ambiguous. Outgoing requests may try to - * find the transport by name and pjproject only finds the first - * one registered. + * and address family because it would be ambiguous. Outgoing + * requests may try to find the transport by name and pjproject + * only finds the first one registered. */ pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE, "ws", 5060, &transport_type_wss); + pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_IPV6, "ws", 5060, &transport_type_wss_ipv6); if (ast_sip_register_service(&websocket_module) != PJ_SUCCESS) { return AST_MODULE_LOAD_DECLINE; diff --git a/third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch b/third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch new file mode 100644 index 000000000..796473a3c --- /dev/null +++ b/third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch @@ -0,0 +1,62 @@ +From daeb0956524606b597704a90b54d81340e10b3e4 Mon Sep 17 00:00:00 2001 +From: Joshua Colp <jcolp@digium.com> +Date: Tue, 7 Mar 2017 12:32:49 +0000 +Subject: [PATCH] Add support for registering IPv6 transport type. + +This change allows an IPv6 transport type to be registered +and used. The IPv4 transport is found (if available) and the +IPv4 flag added to its type to match how the finding of +IPv6 transport types works. +--- + pjsip/src/pjsip/sip_transport.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c +index 7df6138..ce72814 100644 +--- a/pjsip/src/pjsip/sip_transport.c ++++ b/pjsip/src/pjsip/sip_transport.c +@@ -236,6 +236,7 @@ PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag, + int *p_tp_type) + { + unsigned i; ++ pjsip_transport_type_e parent = 0; + + PJ_ASSERT_RETURN(tp_flag && tp_name && def_port, PJ_EINVAL); + PJ_ASSERT_RETURN(pj_ansi_strlen(tp_name) < +@@ -243,6 +244,11 @@ PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag, + PJ_ENAMETOOLONG); + + for (i=1; i<PJ_ARRAY_SIZE(transport_names); ++i) { ++ if (tp_flag & PJSIP_TRANSPORT_IPV6 && ++ pj_stricmp2(&transport_names[i].name, tp_name) == 0) ++ { ++ parent = transport_names[i].type; ++ } + if (transport_names[i].type == 0) + break; + } +@@ -250,14 +256,19 @@ PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag, + if (i == PJ_ARRAY_SIZE(transport_names)) + return PJ_ETOOMANY; + +- transport_names[i].type = (pjsip_transport_type_e)i; ++ if (tp_flag & PJSIP_TRANSPORT_IPV6 && parent) { ++ transport_names[i].type = parent | PJSIP_TRANSPORT_IPV6; ++ } else { ++ transport_names[i].type = (pjsip_transport_type_e)i; ++ } ++ + transport_names[i].port = (pj_uint16_t)def_port; + pj_ansi_strcpy(transport_names[i].name_buf, tp_name); + transport_names[i].name = pj_str(transport_names[i].name_buf); + transport_names[i].flag = tp_flag; + + if (p_tp_type) +- *p_tp_type = i; ++ *p_tp_type = transport_names[i].type; + + return PJ_SUCCESS; + } +-- +2.7.4 + |